From b4c893a62c71ac28795f8fcefb375131833afd0c Mon Sep 17 00:00:00 2001 From: nagachika Date: Sat, 11 Jul 2020 16:10:41 +0900 Subject: OpenSSL 1.1.1 introduces a new '.include' directive. Update our config parser to support that. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As mentioned in the referenced GitHub issue, we should use the OpenSSL API instead of implementing the parsing logic ourselves, but it will need backwards-incompatible changes which we can't backport to stable versions. So continue to use the Ruby implementation for now. References: https://github.com/ruby/openssl/issues/208 https://github.com/ruby/openssl/pull/216 The original patch was written by Kazuki Yamaguchi and the patch for ruby_2_7 branch was prepared by Vít Ondruch. --- ext/openssl/lib/openssl/config.rb | 54 ++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 18 deletions(-) (limited to 'ext') diff --git a/ext/openssl/lib/openssl/config.rb b/ext/openssl/lib/openssl/config.rb index 48d8be0069..78a2da9eb9 100644 --- a/ext/openssl/lib/openssl/config.rb +++ b/ext/openssl/lib/openssl/config.rb @@ -77,29 +77,44 @@ module OpenSSL def parse_config_lines(io) section = 'default' data = {section => {}} - while definition = get_definition(io) + io_stack = [io] + while definition = get_definition(io_stack) definition = clear_comments(definition) next if definition.empty? - if definition[0] == ?[ + case definition + when /\A\[/ if /\[([^\]]*)\]/ =~ definition section = $1.strip data[section] ||= {} else raise ConfigError, "missing close square bracket" end - else - if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition - if $2 - section = $1 - key = $2 - else - key = $1 + when /\A\.include (\s*=\s*)?(.+)\z/ + path = $2 + if File.directory?(path) + files = Dir.glob(File.join(path, "*.{cnf,conf}"), File::FNM_EXTGLOB) + else + files = [path] + end + + files.each do |filename| + begin + io_stack << StringIO.new(File.read(filename)) + rescue + raise ConfigError, "could not include file '%s'" % filename end - value = unescape_value(data, section, $3) - (data[section] ||= {})[key] = value.strip + end + when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ + if $2 + section = $1 + key = $2 else - raise ConfigError, "missing equal sign" + key = $1 end + value = unescape_value(data, section, $3) + (data[section] ||= {})[key] = value.strip + else + raise ConfigError, "missing equal sign" end end data @@ -212,10 +227,10 @@ module OpenSSL scanned.join end - def get_definition(io) - if line = get_line(io) + def get_definition(io_stack) + if line = get_line(io_stack) while /[^\\]\\\z/ =~ line - if extra = get_line(io) + if extra = get_line(io_stack) line += extra else break @@ -225,9 +240,12 @@ module OpenSSL end end - def get_line(io) - if line = io.gets - line.gsub(/[\r\n]*/, '') + def get_line(io_stack) + while io = io_stack.last + if line = io.gets + return line.gsub(/[\r\n]*/, '') + end + io_stack.pop end end end -- cgit v1.2.3