# class OpenSSL::Config

# `OpenSSL::Config`¶ ↑

Configuration for the openssl library.

Many system's installation of openssl library will depend on your system configuration. See the value of `OpenSSL::Config::DEFAULT_CONFIG_FILE` for the location of the file for your host.

See also www.openssl.org/docs/apps/config.html

### Constants

DEFAULT_CONFIG_FILE

  The default system configuration file for openssl

ESCAPE_MAP

  escaped char map

QUOTE_REGEXP_DQ

  escape with backslash and doubled dq

QUOTE_REGEXP_SQ

  escape with backslash

### Public Class Methods

new(filename = nil) click to toggle source

Creates an instance of OpenSSL's configuration class.

This can be used in contexts like `OpenSSL::X509::ExtensionFactory.config=`

If the optional filename parameter is provided, then it is read in and parsed via parse_config.

This can raise `IO` exceptions based on the access, or availability of the file. A `ConfigError` exception may be raised depending on the validity of the data being configured.

    # File ext/openssl/lib/openssl/config.rb, line 264
    def initialize(filename = nil)
      @data = {}
      if filename
        File.open(filename.to_s) do |file|
          Config.parse_config(file).each do |section, hash|
            set_section(section, hash)
          end
        end
      end
    end

parse(string) click to toggle source

Parses a given string as a blob that contains configuration for `OpenSSL`.

If the source of the `IO` is a file, then consider using parse_config.

    # File ext/openssl/lib/openssl/config.rb, line 37
    def parse(string)
      c = new()
      parse_config(StringIO.new(string)).each do |section, hash|
        c.set_section(section, hash)
      end
      c
    end

parse_config(io) click to toggle source

Parses the configuration data read from io, see also parse.

Raises a `ConfigError` on invalid configuration data.

    # File ext/openssl/lib/openssl/config.rb, line 53
    def parse_config(io)
      begin
        parse_config_lines(io)
      rescue => error
        raise ConfigError, "error in line #{io.lineno}: " + error.message
      end
    end

### Private Class Methods

clear_comments(line) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 192
    def clear_comments(line)
      # FCOMMENT
      if m = line.match(/\A([\t\n\f ]*);.*\z/)
        return m[1]
      end
      # COMMENT
      scanned = []
      while m = line.match(/[#'"\\]/)
        scanned << m.pre_match
        c = m[0]
        line = m.post_match
        case c
        when '#'
          line = nil
          break
        when "'", '"'
          regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ
          scanned << c
          if m = line.match(regexp)
            scanned << m[0]
            line = m.post_match
          else
            scanned << line
            line = nil
            break
          end
        when "\\"
          scanned << c
          scanned << line.slice!(0, 1)
        else
          raise 'must not reaced'
        end
      end
      scanned << line
      scanned.join
    end

extract_reference(value) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 177
    def extract_reference(value)
      rest = ''
      if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/)
        value = m[1] || m[2]
        rest = m.post_match
      elsif [?(, ?{].include?(value[0])
        raise ConfigError, "no close brace"
      end
      if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/)
        return m[0], m.post_match + rest
      else
        raise
      end
    end

get_definition(io_stack) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 229
    def get_definition(io_stack)
      if line = get_line(io_stack)
        while /[^\\]\\\z/ =~ line
          if extra = get_line(io_stack)
            line += extra
          else
            break
          end
        end
        return line.strip
      end
    end

get_line(io_stack) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 242
    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

parse_config_lines(io) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 76
    def parse_config_lines(io)
      section = 'default'
      data = {section => {}}
      io_stack = [io]
      while definition = get_definition(io_stack)
        definition = clear_comments(definition)
        next if definition.empty?
        case definition
        when /\A\[/
          if /\[([^\]]*)\]/ =~ definition
            section = $1.strip
            data[section] ||= {}
          else
            raise ConfigError, "missing close square bracket"
          end
        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
          end
        when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/
          if $2
            section = $1
            key = $2
          else
            key = $1
          end
          value = unescape_value(data, section, $3)
          (data[section] ||= {})[key] = value.strip
        else
          raise ConfigError, "missing equal sign"
        end
      end
      data
    end

unescape_value(data, section, value) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 134
    def unescape_value(data, section, value)
      scanned = []
      while m = value.match(/['"\\$]/)
        scanned << m.pre_match
        c = m[0]
        value = m.post_match
        case c
        when "'"
          if m = value.match(QUOTE_REGEXP_SQ)
            scanned << m[1].gsub(/\\(.)/, '\\1')
            value = m.post_match
          else
            break
          end
        when '"'
          if m = value.match(QUOTE_REGEXP_DQ)
            scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1')
            value = m.post_match
          else
            break
          end
        when "\\"
          c = value.slice!(0, 1)
          scanned << (ESCAPE_MAP[c] || c)
        when "$"
          ref, value = extract_reference(value)
          refsec = section
          if ref.index('::')
            refsec, ref = ref.split('::', 2)
          end
          if v = get_key_string(data, refsec, ref)
            scanned << v
          else
            raise ConfigError, "variable has no value"
          end
        else
          raise 'must not reaced'
        end
      end
      scanned << value
      scanned.join
    end

### Public Instance Methods

[](section) click to toggle source

Get a specific section from the current configuration

Given the following configurating file being loaded:

    config = OpenSSL::Config.load('foo.cnf')
      #=> #<OpenSSL::Config sections=["default"]>
    puts config.to_s
      #=> [ default ]
      #   foo=bar

You can get a hash of the specific section like so:

    config['default']
      #=> {"foo"=>"bar"}

    # File ext/openssl/lib/openssl/config.rb, line 360
    def [](section)
      @data[section] || {}
    end

[]=(section, pairs) click to toggle source

*Deprecated in v2.2.0*. This method will be removed in a future release.

Sets a specific section name with a `Hash` pairs.

Given the following configuration being created:

    config = OpenSSL::Config.new
      #=> #<OpenSSL::Config sections=[]>
    config['default'] = {"foo"=>"bar","baz"=>"buz"}
      #=> {"foo"=>"bar", "baz"=>"buz"}
    puts config.to_s
      #=> [ default ]
      #   foo=bar
      #   baz=buz

It's important to note that this will essentially merge any of the keys in pairs with the existing section. For example:

    config['default']
      #=> {"foo"=>"bar", "baz"=>"buz"}
    config['default'] = {"foo" => "changed"}
      #=> {"foo"=>"changed"}
    config['default']
      #=> {"foo"=>"changed", "baz"=>"buz"}

    # File ext/openssl/lib/openssl/config.rb, line 399
    def []=(section, pairs)
      check_modify
      set_section(section, pairs)
    end

add_value(section, key, value) click to toggle source

*Deprecated in v2.2.0*. This method will be removed in a future release.

`Set` the target key with a given value under a specific section.

Given the following configurating file being loaded:

    config = OpenSSL::Config.load('foo.cnf')
      #=> #<OpenSSL::Config sections=["default"]>
    puts config.to_s
      #=> [ default ]
      #   foo=bar

You can set the value of foo under the default section to a new value:

    config.add_value('default', 'foo', 'buzz')
      #=> "buzz"
    puts config.to_s
      #=> [ default ]
      #   foo=buzz

    # File ext/openssl/lib/openssl/config.rb, line 339
    def add_value(section, key, value)
      check_modify
      (@data[section] ||= {})[key] = value
    end

each() { |section, key, value| ... } click to toggle source

For a block.

Receive the section and its pairs for the current configuration.

    config.each do |section, key, value|
      # ...
    end

    # File ext/openssl/lib/openssl/config.rb, line 464
    def each
      @data.each do |section, hash|
        hash.each do |key, value|
          yield [section, key, value]
        end
      end
    end

get_value(section, key) click to toggle source

Gets the value of key from the given section

Given the following configurating file being loaded:

    config = OpenSSL::Config.load('foo.cnf')
      #=> #<OpenSSL::Config sections=["default"]>
    puts config.to_s
      #=> [ default ]
      #   foo=bar

You can get a specific value from the config if you know the section and key like so:

    config.get_value('default','foo')
      #=> "bar"

    # File ext/openssl/lib/openssl/config.rb, line 292
    def get_value(section, key)
      if section.nil?
        raise TypeError.new('nil not allowed')
      end
      section = 'default' if section.empty?
      get_key_string(section, key)
    end

inspect() click to toggle source

`String` representation of this configuration object, including the class name and its sections.

    # File ext/openssl/lib/openssl/config.rb, line 475
    def inspect
      "#<#{self.class.name} sections=#{sections.inspect}>"
    end

sections() click to toggle source

Get the names of all sections in the current configuration

    # File ext/openssl/lib/openssl/config.rb, line 413
    def sections
      @data.keys
    end

to_s() click to toggle source

Get the parsable form of the current configuration

Given the following configuration being created:

    config = OpenSSL::Config.new
      #=> #<OpenSSL::Config sections=[]>
    config['default'] = {"foo"=>"bar","baz"=>"buz"}
      #=> {"foo"=>"bar", "baz"=>"buz"}
    puts config.to_s
      #=> [ default ]
      #   foo=bar
      #   baz=buz

You can parse get the serialized configuration using `to_s` and then parse it later:

    serialized_config = config.to_s
    # much later...
    new_config = OpenSSL::Config.parse(serialized_config)
      #=> #<OpenSSL::Config sections=["default"]>
    puts new_config
      #=> [ default ]
          foo=bar
          baz=buz

    # File ext/openssl/lib/openssl/config.rb, line 443
    def to_s
      ary = []
      @data.keys.sort.each do |section|
        ary << "[ #{section} ]\n"
        @data[section].keys.each do |key|
          ary << "#{key}=#{@data[section][key]}\n"
        end
        ary << "\n"
      end
      ary.join
    end

### Private Instance Methods

check_modify() click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 491
    def check_modify
      warn "#{caller(2, 1)[0]}: warning: do not modify OpenSSL::Config; this " \
        "method is deprecated and will be removed in a future release."
      raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen?
    end

get_key_string(section, key) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 497
    def get_key_string(section, key)
      Config.get_key_string(@data, section, key)
    end

initialize_copy(other) click to toggle source

    # File ext/openssl/lib/openssl/config.rb, line 487
    def initialize_copy(other)
      @data = other.data.dup
    end