File: webrick/ssl.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: WEBrick#11
  class: GenericServer#81
inherits from
  Object ( Builtin-Module )
has properties
method: ssl_context #82
method: listen (2/E) / 2 #86
method: setup_ssl_context / 1 #102
  module: Config#12
has properties
constant: SSL #15
  module: Utils#38
has properties
function: create_self_signed_cert / 3 #39

Class Hierarchy

Object ( Builtin-Module )
  GenericServer ( WEBrick ) #81

Code

   1  #
   2  # ssl.rb -- SSL/TLS enhancement for GenericServer
   3  #
   4  # Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
   5  # 
   6  # $Id: ssl.rb 29858 2010-11-22 07:21:52Z shyouhei $
   7 
   8  require 'webrick'
   9  require 'openssl'
  10 
  11  module WEBrick
  12    module Config
  13      svrsoft = General[:ServerSoftware]
  14      osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
  15      SSL = {
  16        :ServerSoftware       => "#{svrsoft} OpenSSL/#{osslv}",
  17        :SSLEnable            => false,
  18        :SSLCertificate       => nil,
  19        :SSLPrivateKey        => nil,
  20        :SSLClientCA          => nil,
  21        :SSLExtraChainCert    => nil,
  22        :SSLCACertificateFile => nil,
  23        :SSLCACertificatePath => nil,
  24        :SSLCertificateStore  => nil,
  25        :SSLVerifyClient      => ::OpenSSL::SSL::VERIFY_NONE,
  26        :SSLVerifyDepth       => nil,
  27        :SSLVerifyCallback    => nil,   # custom verification
  28        :SSLTimeout           => nil,
  29        :SSLOptions           => nil,
  30        :SSLStartImmediately  => true,
  31        # Must specify if you use auto generated certificate.
  32        :SSLCertName          => nil,
  33        :SSLCertComment       => "Generated by Ruby/OpenSSL"
  34      }
  35      General.update(SSL)
  36    end
  37 
  38    module Utils
  39      def create_self_signed_cert(bits, cn, comment)
  40        rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
  41          case p
  42          when 0; $stderr.putc "."  # BN_generate_prime
  43          when 1; $stderr.putc "+"  # BN_generate_prime
  44          when 2; $stderr.putc "*"  # searching good prime,  
  45                                    # n = #of try,
  46                                    # but also data from BN_generate_prime
  47          when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
  48                                    # but also data from BN_generate_prime
  49          else;   $stderr.putc "*"  # BN_generate_prime
  50          end
  51        }
  52        cert = OpenSSL::X509::Certificate.new
  53        cert.version = 2
  54        cert.serial = 1
  55        name = OpenSSL::X509::Name.new(cn)
  56        cert.subject = name
  57        cert.issuer = name
  58        cert.not_before = Time.now
  59        cert.not_after = Time.now + (365*24*60*60)
  60        cert.public_key = rsa.public_key
  61 
  62        ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
  63        ef.issuer_certificate = cert
  64        cert.extensions = [
  65          ef.create_extension("basicConstraints","CA:FALSE"),
  66          ef.create_extension("keyUsage", "keyEncipherment"),
  67          ef.create_extension("subjectKeyIdentifier", "hash"),
  68          ef.create_extension("extendedKeyUsage", "serverAuth"),
  69          ef.create_extension("nsComment", comment),
  70        ]
  71        aki = ef.create_extension("authorityKeyIdentifier",
  72                                  "keyid:always,issuer:always")
  73        cert.add_extension(aki)
  74        cert.sign(rsa, OpenSSL::Digest::SHA1.new)
  75 
  76        return [ cert, rsa ]
  77      end
  78      module_function :create_self_signed_cert
  79    end
  80 
  81    class GenericServer
  82      def ssl_context
  83        @ssl_context ||= nil
  84      end
  85 
  86      def listen(address, port)
  87        listeners = Utils::create_listeners(address, port, @logger)
  88        if @config[:SSLEnable]
  89          unless ssl_context
  90            @ssl_context = setup_ssl_context(@config)
  91            @logger.info("\n" + @config[:SSLCertificate].to_text) 
  92          end
  93          listeners.collect!{|svr|
  94            ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
  95            ssvr.start_immediately = @config[:SSLStartImmediately]
  96            ssvr
  97          }
  98        end
  99        @listeners += listeners
 100      end
 101 
 102      def setup_ssl_context(config)
 103        unless config[:SSLCertificate]
 104          cn = config[:SSLCertName]
 105          comment = config[:SSLCertComment]
 106          cert, key = Utils::create_self_signed_cert(1024, cn, comment)
 107          config[:SSLCertificate] = cert
 108          config[:SSLPrivateKey] = key
 109        end
 110        ctx = OpenSSL::SSL::SSLContext.new
 111        ctx.key = config[:SSLPrivateKey]
 112        ctx.cert = config[:SSLCertificate]
 113        ctx.client_ca = config[:SSLClientCA]
 114        ctx.extra_chain_cert = config[:SSLExtraChainCert]
 115        ctx.ca_file = config[:SSLCACertificateFile]
 116        ctx.ca_path = config[:SSLCACertificatePath]
 117        ctx.cert_store = config[:SSLCertificateStore]
 118        ctx.verify_mode = config[:SSLVerifyClient]
 119        ctx.verify_depth = config[:SSLVerifyDepth]
 120        ctx.verify_callback = config[:SSLVerifyCallback]
 121        ctx.timeout = config[:SSLTimeout]
 122        ctx.options = config[:SSLOptions]
 123        ctx
 124      end
 125    end
 126  end