openssl 2.1.2 → 2.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 (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