openssl 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -7
  3. data/History.md +77 -0
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +24 -14
  6. data/ext/openssl/openssl_missing.h +37 -2
  7. data/ext/openssl/ossl.c +51 -25
  8. data/ext/openssl/ossl.h +8 -5
  9. data/ext/openssl/ossl_asn1.c +26 -1
  10. data/ext/openssl/ossl_bn.c +9 -3
  11. data/ext/openssl/ossl_cipher.c +33 -24
  12. data/ext/openssl/ossl_digest.c +16 -51
  13. data/ext/openssl/ossl_engine.c +2 -12
  14. data/ext/openssl/ossl_hmac.c +5 -11
  15. data/ext/openssl/ossl_kdf.c +3 -19
  16. data/ext/openssl/ossl_ns_spki.c +1 -1
  17. data/ext/openssl/ossl_ocsp.c +6 -11
  18. data/ext/openssl/ossl_ocsp.h +3 -3
  19. data/ext/openssl/ossl_pkcs7.c +3 -19
  20. data/ext/openssl/ossl_pkcs7.h +16 -0
  21. data/ext/openssl/ossl_pkey.c +180 -14
  22. data/ext/openssl/ossl_pkey.h +5 -5
  23. data/ext/openssl/ossl_pkey_dh.c +1 -1
  24. data/ext/openssl/ossl_pkey_dsa.c +2 -2
  25. data/ext/openssl/ossl_pkey_ec.c +29 -0
  26. data/ext/openssl/ossl_pkey_rsa.c +17 -9
  27. data/ext/openssl/ossl_rand.c +2 -40
  28. data/ext/openssl/ossl_ssl.c +109 -25
  29. data/ext/openssl/ossl_ts.c +1514 -0
  30. data/ext/openssl/ossl_ts.h +16 -0
  31. data/ext/openssl/ossl_x509.c +91 -0
  32. data/ext/openssl/ossl_x509cert.c +2 -2
  33. data/ext/openssl/ossl_x509ext.c +14 -0
  34. data/ext/openssl/ossl_x509name.c +8 -4
  35. data/ext/openssl/ossl_x509store.c +0 -2
  36. data/lib/openssl.rb +25 -9
  37. data/lib/openssl/bn.rb +1 -1
  38. data/lib/openssl/buffering.rb +33 -17
  39. data/lib/openssl/cipher.rb +1 -1
  40. data/lib/openssl/config.rb +53 -26
  41. data/lib/openssl/digest.rb +10 -12
  42. data/lib/openssl/hmac.rb +13 -0
  43. data/lib/openssl/marshal.rb +30 -0
  44. data/lib/openssl/pkcs5.rb +1 -1
  45. data/lib/openssl/pkey.rb +18 -1
  46. data/lib/openssl/ssl.rb +46 -7
  47. data/lib/openssl/version.rb +5 -0
  48. data/lib/openssl/x509.rb +155 -1
  49. metadata +8 -6
  50. data/ext/openssl/deprecation.rb +0 -23
  51. data/ext/openssl/ossl_version.h +0 -15
@@ -0,0 +1,16 @@
1
+ /*
2
+ *
3
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licenced under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+
11
+ #if !defined(_OSSL_TS_H_)
12
+ #define _OSSL_TS_H_
13
+
14
+ void Init_ossl_ts(void);
15
+
16
+ #endif
@@ -44,7 +44,13 @@ Init_ossl_x509(void)
44
44
  Init_ossl_x509revoked();
45
45
  Init_ossl_x509store();
46
46
 
47
+ /* Constants are up-to-date with 1.1.1. */
48
+
49
+ /* Certificate verification error code */
47
50
  DefX509Const(V_OK);
51
+ #if defined(X509_V_ERR_UNSPECIFIED) /* 1.0.1r, 1.0.2f, 1.1.0 */
52
+ DefX509Const(V_ERR_UNSPECIFIED);
53
+ #endif
48
54
  DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT);
49
55
  DefX509Const(V_ERR_UNABLE_TO_GET_CRL);
50
56
  DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
@@ -76,8 +82,73 @@ Init_ossl_x509(void)
76
82
  DefX509Const(V_ERR_AKID_SKID_MISMATCH);
77
83
  DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
78
84
  DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
85
+ DefX509Const(V_ERR_UNABLE_TO_GET_CRL_ISSUER);
86
+ DefX509Const(V_ERR_UNHANDLED_CRITICAL_EXTENSION);
87
+ DefX509Const(V_ERR_KEYUSAGE_NO_CRL_SIGN);
88
+ DefX509Const(V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
89
+ DefX509Const(V_ERR_INVALID_NON_CA);
90
+ DefX509Const(V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
91
+ DefX509Const(V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
92
+ DefX509Const(V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
93
+ DefX509Const(V_ERR_INVALID_EXTENSION);
94
+ DefX509Const(V_ERR_INVALID_POLICY_EXTENSION);
95
+ DefX509Const(V_ERR_NO_EXPLICIT_POLICY);
96
+ DefX509Const(V_ERR_DIFFERENT_CRL_SCOPE);
97
+ DefX509Const(V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
98
+ DefX509Const(V_ERR_UNNESTED_RESOURCE);
99
+ DefX509Const(V_ERR_PERMITTED_VIOLATION);
100
+ DefX509Const(V_ERR_EXCLUDED_VIOLATION);
101
+ DefX509Const(V_ERR_SUBTREE_MINMAX);
79
102
  DefX509Const(V_ERR_APPLICATION_VERIFICATION);
103
+ DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
104
+ DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
105
+ DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX);
106
+ DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR);
107
+ #if defined(X509_V_ERR_PATH_LOOP)
108
+ DefX509Const(V_ERR_PATH_LOOP);
109
+ #endif
110
+ #if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
111
+ DefX509Const(V_ERR_SUITE_B_INVALID_VERSION);
112
+ DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM);
113
+ DefX509Const(V_ERR_SUITE_B_INVALID_CURVE);
114
+ DefX509Const(V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM);
115
+ DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED);
116
+ DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256);
117
+ #endif
118
+ #if defined(X509_V_ERR_HOSTNAME_MISMATCH)
119
+ DefX509Const(V_ERR_HOSTNAME_MISMATCH);
120
+ DefX509Const(V_ERR_EMAIL_MISMATCH);
121
+ DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
122
+ #endif
123
+ #if defined(X509_V_ERR_DANE_NO_MATCH)
124
+ DefX509Const(V_ERR_DANE_NO_MATCH);
125
+ #endif
126
+ #if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
127
+ DefX509Const(V_ERR_EE_KEY_TOO_SMALL);
128
+ DefX509Const(V_ERR_CA_KEY_TOO_SMALL);
129
+ DefX509Const(V_ERR_CA_MD_TOO_WEAK);
130
+ #endif
131
+ #if defined(X509_V_ERR_INVALID_CALL)
132
+ DefX509Const(V_ERR_INVALID_CALL);
133
+ #endif
134
+ #if defined(X509_V_ERR_STORE_LOOKUP)
135
+ DefX509Const(V_ERR_STORE_LOOKUP);
136
+ #endif
137
+ #if defined(X509_V_ERR_NO_VALID_SCTS)
138
+ DefX509Const(V_ERR_NO_VALID_SCTS);
139
+ #endif
140
+ #if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
141
+ DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION);
142
+ #endif
143
+ #if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
144
+ DefX509Const(V_ERR_OCSP_VERIFY_NEEDED);
145
+ DefX509Const(V_ERR_OCSP_VERIFY_FAILED);
146
+ DefX509Const(V_ERR_OCSP_CERT_UNKNOWN);
147
+ #endif
80
148
 
149
+ /* Certificate verify flags */
150
+ /* Set by Store#flags= and StoreContext#flags=. */
151
+ DefX509Const(V_FLAG_USE_CHECK_TIME);
81
152
  /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the
82
153
  * certificate chain leaf. */
83
154
  DefX509Const(V_FLAG_CRL_CHECK);
@@ -122,6 +193,26 @@ Init_ossl_x509(void)
122
193
  * Enabled by default in OpenSSL >= 1.1.0. */
123
194
  DefX509Const(V_FLAG_TRUSTED_FIRST);
124
195
  #endif
196
+ #if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY)
197
+ /* Set by Store#flags= and StoreContext#flags=.
198
+ * Enables Suite B 128 bit only mode. */
199
+ DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY);
200
+ #endif
201
+ #if defined(X509_V_FLAG_SUITEB_192_LOS)
202
+ /* Set by Store#flags= and StoreContext#flags=.
203
+ * Enables Suite B 192 bit only mode. */
204
+ DefX509Const(V_FLAG_SUITEB_192_LOS);
205
+ #endif
206
+ #if defined(X509_V_FLAG_SUITEB_128_LOS)
207
+ /* Set by Store#flags= and StoreContext#flags=.
208
+ * Enables Suite B 128 bit mode allowing 192 bit algorithms. */
209
+ DefX509Const(V_FLAG_SUITEB_128_LOS);
210
+ #endif
211
+ #if defined(X509_V_FLAG_PARTIAL_CHAIN)
212
+ /* Set by Store#flags= and StoreContext#flags=.
213
+ * Allows partial chains if at least one certificate is in trusted store. */
214
+ DefX509Const(V_FLAG_PARTIAL_CHAIN);
215
+ #endif
125
216
  #if defined(X509_V_FLAG_NO_ALT_CHAINS)
126
217
  /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
127
218
  * a alternative chain. No effect in OpenSSL >= 1.1.0. */
@@ -788,7 +788,7 @@ Init_ossl_x509cert(void)
788
788
  * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
789
789
  * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
790
790
  * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
791
- * root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
791
+ * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256'))
792
792
  *
793
793
  * The next step is to create the end-entity certificate using the root CA
794
794
  * certificate.
@@ -807,7 +807,7 @@ Init_ossl_x509cert(void)
807
807
  * ef.issuer_certificate = root_ca
808
808
  * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
809
809
  * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
810
- * cert.sign(root_key, OpenSSL::Digest::SHA256.new)
810
+ * cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
811
811
  *
812
812
  */
813
813
  cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
@@ -402,6 +402,19 @@ ossl_x509ext_get_value(VALUE obj)
402
402
  return ret;
403
403
  }
404
404
 
405
+ static VALUE
406
+ ossl_x509ext_get_value_der(VALUE obj)
407
+ {
408
+ X509_EXTENSION *ext;
409
+ ASN1_OCTET_STRING *value;
410
+
411
+ GetX509Ext(obj, ext);
412
+ if ((value = X509_EXTENSION_get_data(ext)) == NULL)
413
+ ossl_raise(eX509ExtError, NULL);
414
+
415
+ return rb_str_new((const char *)value->data, value->length);
416
+ }
417
+
405
418
  static VALUE
406
419
  ossl_x509ext_get_critical(VALUE obj)
407
420
  {
@@ -472,6 +485,7 @@ Init_ossl_x509ext(void)
472
485
  rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
473
486
  rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
474
487
  rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
488
+ rb_define_method(cX509Ext, "value_der", ossl_x509ext_get_value_der, 0);
475
489
  rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
476
490
  rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
477
491
  }
@@ -270,7 +270,7 @@ x509name_print(VALUE self, unsigned long iflag)
270
270
  if (!out)
271
271
  ossl_raise(eX509NameError, NULL);
272
272
  ret = X509_NAME_print_ex(out, name, 0, iflag);
273
- if (ret < 0 || iflag == XN_FLAG_COMPAT && ret == 0) {
273
+ if (ret < 0 || (iflag == XN_FLAG_COMPAT && ret == 0)) {
274
274
  BIO_free(out);
275
275
  ossl_raise(eX509NameError, "X509_NAME_print_ex");
276
276
  }
@@ -387,17 +387,21 @@ ossl_x509name_cmp0(VALUE self, VALUE other)
387
387
 
388
388
  /*
389
389
  * call-seq:
390
- * name.cmp(other) -> -1 | 0 | 1
391
- * name <=> other -> -1 | 0 | 1
390
+ * name.cmp(other) -> -1 | 0 | 1 | nil
391
+ * name <=> other -> -1 | 0 | 1 | nil
392
392
  *
393
393
  * Compares this Name with _other_ and returns +0+ if they are the same and +-1+
394
394
  * or ++1+ if they are greater or less than each other respectively.
395
+ * Returns +nil+ if they are not comparable (i.e. different types).
395
396
  */
396
397
  static VALUE
397
398
  ossl_x509name_cmp(VALUE self, VALUE other)
398
399
  {
399
400
  int result;
400
401
 
402
+ if (!rb_obj_is_kind_of(other, cX509Name))
403
+ return Qnil;
404
+
401
405
  result = ossl_x509name_cmp0(self, other);
402
406
  if (result < 0) return INT2FIX(-1);
403
407
  if (result > 0) return INT2FIX(1);
@@ -494,7 +498,7 @@ ossl_x509name_to_der(VALUE self)
494
498
  * You can create a Name by parsing a distinguished name String or by
495
499
  * supplying the distinguished name as an Array.
496
500
  *
497
- * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
501
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
498
502
  *
499
503
  * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
500
504
  */
@@ -304,7 +304,6 @@ ossl_x509store_add_file(VALUE self, VALUE file)
304
304
  char *path = NULL;
305
305
 
306
306
  if(file != Qnil){
307
- rb_check_safe_obj(file);
308
307
  path = StringValueCStr(file);
309
308
  }
310
309
  GetX509Store(self, store);
@@ -340,7 +339,6 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
340
339
  char *path = NULL;
341
340
 
342
341
  if(dir != Qnil){
343
- rb_check_safe_obj(dir);
344
342
  path = StringValueCStr(dir);
345
343
  }
346
344
  GetX509Store(self, store);
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  =begin
3
3
  = Info
4
4
  'OpenSSL for Ruby 2' project
@@ -12,11 +12,27 @@
12
12
 
13
13
  require 'openssl.so'
14
14
 
15
- require 'openssl/bn'
16
- require 'openssl/pkey'
17
- require 'openssl/cipher'
18
- require 'openssl/config'
19
- require 'openssl/digest'
20
- require 'openssl/x509'
21
- require 'openssl/ssl'
22
- require 'openssl/pkcs5'
15
+ require_relative 'openssl/bn'
16
+ require_relative 'openssl/pkey'
17
+ require_relative 'openssl/cipher'
18
+ require_relative 'openssl/config'
19
+ require_relative 'openssl/digest'
20
+ require_relative 'openssl/hmac'
21
+ require_relative 'openssl/x509'
22
+ require_relative 'openssl/ssl'
23
+ require_relative 'openssl/pkcs5'
24
+ require_relative 'openssl/version'
25
+
26
+ module OpenSSL
27
+ # call-seq:
28
+ # OpenSSL.secure_compare(string, string) -> boolean
29
+ #
30
+ # Constant time memory comparison. Inputs are hashed using SHA-256 to mask
31
+ # the length of the secret. Returns +true+ if the strings are identical,
32
+ # +false+ otherwise.
33
+ def self.secure_compare(a, b)
34
+ hashed_a = OpenSSL::Digest.digest('SHA256', a)
35
+ hashed_b = OpenSSL::Digest.digest('SHA256', b)
36
+ OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
37
+ end
38
+ end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #--
3
3
  #
4
4
  # = Ruby-space definitions that completes C-space funcs for BN
@@ -1,5 +1,5 @@
1
1
  # coding: binary
2
- # frozen_string_literal: false
2
+ # frozen_string_literal: true
3
3
  #--
4
4
  #= Info
5
5
  # 'OpenSSL for Ruby 2' project
@@ -22,6 +22,29 @@
22
22
  module OpenSSL::Buffering
23
23
  include Enumerable
24
24
 
25
+ # A buffer which will retain binary encoding.
26
+ class Buffer < String
27
+ BINARY = Encoding::BINARY
28
+
29
+ def initialize
30
+ super
31
+
32
+ force_encoding(BINARY)
33
+ end
34
+
35
+ def << string
36
+ if string.encoding == BINARY
37
+ super(string)
38
+ else
39
+ super(string.b)
40
+ end
41
+
42
+ return self
43
+ end
44
+
45
+ alias concat <<
46
+ end
47
+
25
48
  ##
26
49
  # The "sync mode" of the SSLSocket.
27
50
  #
@@ -40,7 +63,7 @@ module OpenSSL::Buffering
40
63
  def initialize(*)
41
64
  super
42
65
  @eof = false
43
- @rbuffer = ""
66
+ @rbuffer = Buffer.new
44
67
  @sync = @io.sync
45
68
  end
46
69
 
@@ -312,24 +335,19 @@ module OpenSSL::Buffering
312
335
  # buffer is flushed to the underlying socket.
313
336
 
314
337
  def do_write(s)
315
- @wbuffer = "" unless defined? @wbuffer
338
+ @wbuffer = Buffer.new unless defined? @wbuffer
316
339
  @wbuffer << s
317
340
  @wbuffer.force_encoding(Encoding::BINARY)
318
341
  @sync ||= false
319
- if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
320
- remain = idx ? idx + $/.size : @wbuffer.length
321
- nwritten = 0
322
- while remain > 0
323
- str = @wbuffer[nwritten,remain]
342
+ if @sync or @wbuffer.size > BLOCK_SIZE
343
+ until @wbuffer.empty?
324
344
  begin
325
- nwrote = syswrite(str)
345
+ nwrote = syswrite(@wbuffer)
326
346
  rescue Errno::EAGAIN
327
347
  retry
328
348
  end
329
- remain -= nwrote
330
- nwritten += nwrote
349
+ @wbuffer[0, nwrote] = ""
331
350
  end
332
- @wbuffer[0,nwritten] = ""
333
351
  end
334
352
  end
335
353
 
@@ -403,15 +421,13 @@ module OpenSSL::Buffering
403
421
  # See IO#puts for full details.
404
422
 
405
423
  def puts(*args)
406
- s = ""
424
+ s = Buffer.new
407
425
  if args.empty?
408
426
  s << "\n"
409
427
  end
410
428
  args.each{|arg|
411
429
  s << arg.to_s
412
- if $/ && /\n\z/ !~ s
413
- s << "\n"
414
- end
430
+ s.sub!(/(?<!\n)\z/, "\n")
415
431
  }
416
432
  do_write(s)
417
433
  nil
@@ -423,7 +439,7 @@ module OpenSSL::Buffering
423
439
  # See IO#print for full details.
424
440
 
425
441
  def print(*args)
426
- s = ""
442
+ s = Buffer.new
427
443
  args.each{ |arg| s << arg.to_s }
428
444
  do_write(s)
429
445
  nil
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #--
3
3
  # = Ruby-space predefined Cipher subclasses
4
4
  #
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  =begin
3
3
  = Ruby-space definitions that completes C-space funcs for Config
4
4
 
@@ -37,7 +37,7 @@ module OpenSSL
37
37
  def parse(string)
38
38
  c = new()
39
39
  parse_config(StringIO.new(string)).each do |section, hash|
40
- c[section] = hash
40
+ c.set_section(section, hash)
41
41
  end
42
42
  c
43
43
  end
@@ -53,9 +53,8 @@ module OpenSSL
53
53
  def parse_config(io)
54
54
  begin
55
55
  parse_config_lines(io)
56
- rescue ConfigError => e
57
- e.message.replace("error in line #{io.lineno}: " + e.message)
58
- raise
56
+ rescue => error
57
+ raise ConfigError, "error in line #{io.lineno}: " + error.message
59
58
  end
60
59
  end
61
60
 
@@ -77,29 +76,44 @@ module OpenSSL
77
76
  def parse_config_lines(io)
78
77
  section = 'default'
79
78
  data = {section => {}}
80
- while definition = get_definition(io)
79
+ io_stack = [io]
80
+ while definition = get_definition(io_stack)
81
81
  definition = clear_comments(definition)
82
82
  next if definition.empty?
83
- if definition[0] == ?[
83
+ case definition
84
+ when /\A\[/
84
85
  if /\[([^\]]*)\]/ =~ definition
85
86
  section = $1.strip
86
87
  data[section] ||= {}
87
88
  else
88
89
  raise ConfigError, "missing close square bracket"
89
90
  end
90
- else
91
- if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition
92
- if $2
93
- section = $1
94
- key = $2
95
- else
96
- key = $1
91
+ when /\A\.include (\s*=\s*)?(.+)\z/
92
+ path = $2
93
+ if File.directory?(path)
94
+ files = Dir.glob(File.join(path, "*.{cnf,conf}"), File::FNM_EXTGLOB)
95
+ else
96
+ files = [path]
97
+ end
98
+
99
+ files.each do |filename|
100
+ begin
101
+ io_stack << StringIO.new(File.read(filename))
102
+ rescue
103
+ raise ConfigError, "could not include file '%s'" % filename
97
104
  end
98
- value = unescape_value(data, section, $3)
99
- (data[section] ||= {})[key] = value.strip
105
+ end
106
+ when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/
107
+ if $2
108
+ section = $1
109
+ key = $2
100
110
  else
101
- raise ConfigError, "missing equal sign"
111
+ key = $1
102
112
  end
113
+ value = unescape_value(data, section, $3)
114
+ (data[section] ||= {})[key] = value.strip
115
+ else
116
+ raise ConfigError, "missing equal sign"
103
117
  end
104
118
  end
105
119
  data
@@ -212,10 +226,10 @@ module OpenSSL
212
226
  scanned.join
213
227
  end
214
228
 
215
- def get_definition(io)
216
- if line = get_line(io)
229
+ def get_definition(io_stack)
230
+ if line = get_line(io_stack)
217
231
  while /[^\\]\\\z/ =~ line
218
- if extra = get_line(io)
232
+ if extra = get_line(io_stack)
219
233
  line += extra
220
234
  else
221
235
  break
@@ -225,9 +239,12 @@ module OpenSSL
225
239
  end
226
240
  end
227
241
 
228
- def get_line(io)
229
- if line = io.gets
230
- line.gsub(/[\r\n]*/, '')
242
+ def get_line(io_stack)
243
+ while io = io_stack.last
244
+ if line = io.gets
245
+ return line.gsub(/[\r\n]*/, '')
246
+ end
247
+ io_stack.pop
231
248
  end
232
249
  end
233
250
  end
@@ -249,7 +266,7 @@ module OpenSSL
249
266
  if filename
250
267
  File.open(filename.to_s) do |file|
251
268
  Config.parse_config(file).each do |section, hash|
252
- self[section] = hash
269
+ set_section(section, hash)
253
270
  end
254
271
  end
255
272
  end
@@ -298,6 +315,8 @@ module OpenSSL
298
315
  end
299
316
 
300
317
  ##
318
+ # *Deprecated in v2.2.0*. This method will be removed in a future release.
319
+ #
301
320
  # Set the target _key_ with a given _value_ under a specific _section_.
302
321
  #
303
322
  # Given the following configurating file being loaded:
@@ -352,6 +371,8 @@ module OpenSSL
352
371
  end
353
372
 
354
373
  ##
374
+ # *Deprecated in v2.2.0*. This method will be removed in a future release.
375
+ #
355
376
  # Sets a specific _section_ name with a Hash _pairs_.
356
377
  #
357
378
  # Given the following configuration being created:
@@ -377,9 +398,13 @@ module OpenSSL
377
398
  #
378
399
  def []=(section, pairs)
379
400
  check_modify
380
- @data[section] ||= {}
401
+ set_section(section, pairs)
402
+ end
403
+
404
+ def set_section(section, pairs) # :nodoc:
405
+ hash = @data[section] ||= {}
381
406
  pairs.each do |key, value|
382
- self.add_value(section, key, value)
407
+ hash[key] = value
383
408
  end
384
409
  end
385
410
 
@@ -464,6 +489,8 @@ module OpenSSL
464
489
  end
465
490
 
466
491
  def check_modify
492
+ warn "#{caller(2, 1)[0]}: warning: do not modify OpenSSL::Config; this " \
493
+ "method is deprecated and will be removed in a future release."
467
494
  raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen?
468
495
  end
469
496