# class DRb::DRbSSLSocket::SSLConfig

`SSLConfig` handles the needed SSL information for establishing a `DRbSSLSocket` connection, including generating the X509 / RSA pair.

An instance of this config can be passed to `DRbSSLSocket.new`, `DRbSSLSocket.open` and `DRbSSLSocket.open_server`

See `DRb::DRbSSLSocket::SSLConfig.new` for more details

### Constants

DEFAULT

  Default values for a `SSLConfig` instance.

  See `DRb::DRbSSLSocket::SSLConfig.new` for more details

### Public Class Methods

new(config) click to toggle source

Create a new `DRb::DRbSSLSocket::SSLConfig` instance

The `DRb::DRbSSLSocket` will take either a `config` `Hash` or an instance of `SSLConfig`, and will setup the certificate for its session for the configuration. If want it to generate a generic certificate, the bare minimum is to provide the :SSLCertName

### Config options¶ ↑

From `config` Hash:

:SSLCertificate

  An instance of `OpenSSL::X509::Certificate`. If this is not provided, then a generic X509 is generated, with a correspond :SSLPrivateKey

:SSLPrivateKey

  A private key instance, like `OpenSSL::PKey::RSA`. This key must be the key that signed the :SSLCertificate

:SSLClientCA

  An `OpenSSL::X509::Certificate`, or `Array` of certificates that will used as ClientCAs in the SSL Context

:SSLCACertificatePath

  A path to the directory of CA certificates. The certificates must be in PEM format.

:SSLCACertificateFile

  A path to a CA certificate file, in PEM format.

:SSLTmpDhCallback

  A DH callback. See `OpenSSL::SSL::SSLContext.tmp_dh_callback`

:SSLVerifyMode

  This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for available modes. The default is OpenSSL::SSL::VERIFY_NONE

:SSLVerifyDepth

  Number of CA certificates to walk, when verifying a certificate chain.

:SSLVerifyCallback

  A callback to be used for additional verification. See `OpenSSL::SSL::SSLContext.verify_callback`

:SSLCertificateStore

  A `OpenSSL::X509::Store` used for verification of certificates

:SSLCertName

  Issuer name for the certificate. This is required when generating the certificate (if :SSLCertificate and :SSLPrivateKey were not given). The value of this is to be an `Array` of pairs:

      [["C", "Raleigh"], ["ST","North Carolina"],
       ["CN","fqdn.example.com"]]

  See also `OpenSSL::X509::Name`

:SSLCertComment

  A comment to be used for generating the certificate. The default is “Generated by Ruby/OpenSSL”

### Example¶ ↑

These values can be added after the fact, like a `Hash`.

    require 'drb/ssl'
    c = DRb::DRbSSLSocket::SSLConfig.new {}
    c[:SSLCertificate] =
      OpenSSL::X509::Certificate.new(File.read('mycert.crt'))
    c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key'))
    c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
    c[:SSLCACertificatePath] = "/etc/ssl/certs/"
    c.setup_certificate

or

    require 'drb/ssl'
    c = DRb::DRbSSLSocket::SSLConfig.new({
            :SSLCertName => [["CN" => DRb::DRbSSLSocket.getservername]]
            })
    c.setup_certificate

    # File lib/drb/ssl.rb, line 127
    def initialize(config)
      @config  = config
      @cert    = config[:SSLCertificate]
      @pkey    = config[:SSLPrivateKey]
      @ssl_ctx = nil
    end

### Public Instance Methods

[](key) click to toggle source

A convenience method to access the values like a `Hash`

    # File lib/drb/ssl.rb, line 135
    def [](key);
      @config[key] || DEFAULT[key]
    end

accept(tcp) click to toggle source

Accept connection to `IO` `tcp`, with context of the current certificate configuration

    # File lib/drb/ssl.rb, line 150
    def accept(tcp)
      ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
      ssl.sync = true
      ssl.accept
      ssl
    end

connect(tcp) click to toggle source

Connect to `IO` `tcp`, with context of the current certificate configuration

    # File lib/drb/ssl.rb, line 141
    def connect(tcp)
      ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
      ssl.sync = true
      ssl.connect
      ssl
    end

setup_certificate() click to toggle source

Ensures that :SSLCertificate and :SSLPrivateKey have been provided or that a new certificate is generated with the other parameters provided.

    # File lib/drb/ssl.rb, line 160
    def setup_certificate
      if @cert && @pkey
        return
      end

      rsa = OpenSSL::PKey::RSA.new(2048){|p, n|
        next unless self[:verbose]
        case p
        when 0; $stderr.putc "."  # BN_generate_prime
        when 1; $stderr.putc "+"  # BN_generate_prime
        when 2; $stderr.putc "*"  # searching good prime,
                                  # n = #of try,
                                  # but also data from BN_generate_prime
        when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
                                  # but also data from BN_generate_prime
        else;   $stderr.putc "*"  # BN_generate_prime
        end
      }

      cert = OpenSSL::X509::Certificate.new
      cert.version = 3
      cert.serial = 0
      name = OpenSSL::X509::Name.new(self[:SSLCertName])
      cert.subject = name
      cert.issuer = name
      cert.not_before = Time.now
      cert.not_after = Time.now + (365*24*60*60)
      cert.public_key = rsa.public_key

      ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
      cert.extensions = [
        ef.create_extension("basicConstraints","CA:FALSE"),
        ef.create_extension("subjectKeyIdentifier", "hash") ]
      ef.issuer_certificate = cert
      cert.add_extension(ef.create_extension("authorityKeyIdentifier",
                                             "keyid:always,issuer:always"))
      if comment = self[:SSLCertComment]
        cert.add_extension(ef.create_extension("nsComment", comment))
      end
      cert.sign(rsa, "SHA256")

      @cert = cert
      @pkey = rsa
    end

setup_ssl_context() click to toggle source

Establish the `OpenSSL::SSL::SSLContext` with the configuration parameters provided.

    # File lib/drb/ssl.rb, line 207
    def setup_ssl_context
      ctx = ::OpenSSL::SSL::SSLContext.new
      ctx.cert            = @cert
      ctx.key             = @pkey
      ctx.client_ca       = self[:SSLClientCA]
      ctx.ca_path         = self[:SSLCACertificatePath]
      ctx.ca_file         = self[:SSLCACertificateFile]
      ctx.tmp_dh_callback = self[:SSLTmpDhCallback]
      ctx.verify_mode     = self[:SSLVerifyMode]
      ctx.verify_depth    = self[:SSLVerifyDepth]
      ctx.verify_callback = self[:SSLVerifyCallback]
      ctx.cert_store      = self[:SSLCertificateStore]
      @ssl_ctx = ctx
    end