Skip to content
Browse files

Added lib/19/openssl from 1.9.3p0.

  • Loading branch information...
1 parent 36e7e35 commit d711d599d17627d1545a30b3bef7de29cbb70ba8 @brixen brixen committed Dec 23, 2011
Showing with 19,924 additions and 0 deletions.
  1. +25 −0 lib/19/openssl.rb
  2. +35 −0 lib/19/openssl/bn.rb
  3. +448 −0 lib/19/openssl/buffering.rb
  4. +65 −0 lib/19/openssl/cipher.rb
  5. +313 −0 lib/19/openssl/config.rb
  6. +72 −0 lib/19/openssl/digest.rb
  7. +3 −0 lib/19/openssl/ext/.gitignore
  8. +140 −0 lib/19/openssl/ext/extconf.rb
  9. +356 −0 lib/19/openssl/ext/openssl_missing.c
  10. +198 −0 lib/19/openssl/ext/openssl_missing.h
  11. +901 −0 lib/19/openssl/ext/ossl.c
  12. +241 −0 lib/19/openssl/ext/ossl.h
  13. +1,932 −0 lib/19/openssl/ext/ossl_asn1.c
  14. +59 −0 lib/19/openssl/ext/ossl_asn1.h
  15. +86 −0 lib/19/openssl/ext/ossl_bio.c
  16. +21 −0 lib/19/openssl/ext/ossl_bio.h
  17. +854 −0 lib/19/openssl/ext/ossl_bn.c
  18. +25 −0 lib/19/openssl/ext/ossl_bn.h
  19. +567 −0 lib/19/openssl/ext/ossl_cipher.c
  20. +22 −0 lib/19/openssl/ext/ossl_cipher.h
  21. +74 −0 lib/19/openssl/ext/ossl_config.c
  22. +22 −0 lib/19/openssl/ext/ossl_config.h
  23. +438 −0 lib/19/openssl/ext/ossl_digest.c
  24. +22 −0 lib/19/openssl/ext/ossl_digest.h
  25. +415 −0 lib/19/openssl/ext/ossl_engine.c
  26. +20 −0 lib/19/openssl/ext/ossl_engine.h
  27. +270 −0 lib/19/openssl/ext/ossl_hmac.c
  28. +19 −0 lib/19/openssl/ext/ossl_hmac.h
  29. +257 −0 lib/19/openssl/ext/ossl_ns_spki.c
  30. +21 −0 lib/19/openssl/ext/ossl_ns_spki.h
  31. +786 −0 lib/19/openssl/ext/ossl_ocsp.c
  32. +24 −0 lib/19/openssl/ext/ossl_ocsp.h
  33. +212 −0 lib/19/openssl/ext/ossl_pkcs12.c
  34. +15 −0 lib/19/openssl/ext/ossl_pkcs12.h
  35. +101 −0 lib/19/openssl/ext/ossl_pkcs5.c
  36. +6 −0 lib/19/openssl/ext/ossl_pkcs5.h
  37. +1,043 −0 lib/19/openssl/ext/ossl_pkcs7.c
  38. +22 −0 lib/19/openssl/ext/ossl_pkcs7.h
  39. +398 −0 lib/19/openssl/ext/ossl_pkey.c
  40. +141 −0 lib/19/openssl/ext/ossl_pkey.h
  41. +618 −0 lib/19/openssl/ext/ossl_pkey_dh.c
  42. +558 −0 lib/19/openssl/ext/ossl_pkey_dsa.c
  43. +1,594 −0 lib/19/openssl/ext/ossl_pkey_ec.c
  44. +632 −0 lib/19/openssl/ext/ossl_pkey_rsa.c
  45. +202 −0 lib/19/openssl/ext/ossl_rand.c
  46. +20 −0 lib/19/openssl/ext/ossl_rand.h
  47. +2,007 −0 lib/19/openssl/ext/ossl_ssl.c
  48. +36 −0 lib/19/openssl/ext/ossl_ssl.h
  49. +323 −0 lib/19/openssl/ext/ossl_ssl_session.c
  50. +16 −0 lib/19/openssl/ext/ossl_version.h
  51. +104 −0 lib/19/openssl/ext/ossl_x509.c
  52. +114 −0 lib/19/openssl/ext/ossl_x509.h
  53. +275 −0 lib/19/openssl/ext/ossl_x509attr.c
  54. +868 −0 lib/19/openssl/ext/ossl_x509cert.c
  55. +537 −0 lib/19/openssl/ext/ossl_x509crl.c
  56. +471 −0 lib/19/openssl/ext/ossl_x509ext.c
  57. +412 −0 lib/19/openssl/ext/ossl_x509name.c
  58. +468 −0 lib/19/openssl/ext/ossl_x509req.c
Sorry, we could not display the entire diff because it was too big.
View
25 lib/19/openssl.rb
@@ -0,0 +1,25 @@
+=begin
+= $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: openssl.rb 32665 2011-07-25 06:38:44Z nahi $
+=end
+
+require 'openssl/ext/openssl'
+
+require 'openssl/bn'
+require 'openssl/cipher'
+require 'openssl/config'
+require 'openssl/digest'
+require 'openssl/ssl-internal'
+require 'openssl/x509-internal'
+
View
35 lib/19/openssl/bn.rb
@@ -0,0 +1,35 @@
+#--
+#
+# $RCSfile$
+#
+# = Ruby-space definitions that completes C-space funcs for BN
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licenced under the same licence as Ruby.
+# (See the file 'LICENCE'.)
+#
+# = Version
+# $Id: bn.rb 33067 2011-08-25 00:52:10Z drbrain $
+#
+#++
+
+module OpenSSL
+ class BN
+ include Comparable
+ end # BN
+end # OpenSSL
+
+##
+# Add double dispatch to Integer
+#
+class Integer
+ def to_bn
+ OpenSSL::BN::new(self.to_s(16), 16)
+ end
+end # Integer
+
View
448 lib/19/openssl/buffering.rb
@@ -0,0 +1,448 @@
+=begin
+= $RCSfile$ -- Buffering mix-in module.
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: buffering.rb 32012 2011-06-11 14:07:42Z nahi $
+=end
+
+##
+# OpenSSL IO buffering mix-in module.
+#
+# This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
+
+module OpenSSL::Buffering
+ include Enumerable
+
+ ##
+ # The "sync mode" of the SSLSocket.
+ #
+ # See IO#sync for full details.
+
+ attr_accessor :sync
+
+ ##
+ # Default size to read from or write to the SSLSocket for buffer operations.
+
+ BLOCK_SIZE = 1024*16
+
+ def initialize(*args)
+ @eof = false
+ @rbuffer = ""
+ @sync = @io.sync
+ end
+
+ #
+ # for reading.
+ #
+ private
+
+ ##
+ # Fills the buffer from the underlying SSLSocket
+
+ def fill_rbuff
+ begin
+ @rbuffer << self.sysread(BLOCK_SIZE)
+ rescue Errno::EAGAIN
+ retry
+ rescue EOFError
+ @eof = true
+ end
+ end
+
+ ##
+ # Consumes +size+ bytes from the buffer
+
+ def consume_rbuff(size=nil)
+ if @rbuffer.empty?
+ nil
+ else
+ size = @rbuffer.size unless size
+ ret = @rbuffer[0, size]
+ @rbuffer[0, size] = ""
+ ret
+ end
+ end
+
+ public
+
+ ##
+ # Reads +size+ bytes from the stream. If +buf+ is provided it must
+ # reference a string which will receive the data.
+ #
+ # See IO#read for full details.
+
+ def read(size=nil, buf=nil)
+ if size == 0
+ if buf
+ buf.clear
+ return buf
+ else
+ return ""
+ end
+ end
+ until @eof
+ break if size && size <= @rbuffer.size
+ fill_rbuff
+ end
+ ret = consume_rbuff(size) || ""
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ (size && ret.empty?) ? nil : ret
+ end
+
+ ##
+ # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it
+ # must reference a string which will receive the data.
+ #
+ # See IO#readpartial for full details.
+
+ def readpartial(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ return buf
+ else
+ return ""
+ end
+ end
+ if @rbuffer.empty?
+ begin
+ return sysread(maxlen, buf)
+ rescue Errno::EAGAIN
+ retry
+ end
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ raise EOFError if ret.empty?
+ ret
+ end
+
+ ##
+ # Reads at most +maxlen+ bytes in the non-blocking manner.
+ #
+ # When no data can be read without blocking it raises
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
+ #
+ # IO::WaitReadable means SSL needs to read internally so read_nonblock
+ # should be called again when the underlying IO is readable.
+ #
+ # IO::WaitWritable means SSL needs to write internally so read_nonblock
+ # should be called again after the underlying IO is writable.
+ #
+ # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
+ #
+ # # emulates blocking read (readpartial).
+ # begin
+ # result = ssl.read_nonblock(maxlen)
+ # rescue IO::WaitReadable
+ # IO.select([io])
+ # retry
+ # rescue IO::WaitWritable
+ # IO.select(nil, [io])
+ # retry
+ # end
+ #
+ # Note that one reason that read_nonblock writes to the underlying IO is
+ # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
+ # more details. http://www.openssl.org/support/faq.html
+
+ def read_nonblock(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ return buf
+ else
+ return ""
+ end
+ end
+ if @rbuffer.empty?
+ return sysread_nonblock(maxlen, buf)
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ raise EOFError if ret.empty?
+ ret
+ end
+
+ ##
+ # Reads the next "line+ from the stream. Lines are separated by +eol+. If
+ # +limit+ is provided the result will not be longer than the given number of
+ # bytes.
+ #
+ # +eol+ may be a String or Regexp.
+ #
+ # Unlike IO#gets the line read will not be assigned to +$_+.
+ #
+ # Unlike IO#gets the separator must be provided if a limit is provided.
+
+ def gets(eol=$/, limit=nil)
+ idx = @rbuffer.index(eol)
+ until @eof
+ break if idx
+ fill_rbuff
+ idx = @rbuffer.index(eol)
+ end
+ if eol.is_a?(Regexp)
+ size = idx ? idx+$&.size : nil
+ else
+ size = idx ? idx+eol.size : nil
+ end
+ if limit and limit >= 0
+ size = [size, limit].min
+ end
+ consume_rbuff(size)
+ end
+
+ ##
+ # Executes the block for every line in the stream where lines are separated
+ # by +eol+.
+ #
+ # See also #gets
+
+ def each(eol=$/)
+ while line = self.gets(eol)
+ yield line
+ end
+ end
+ alias each_line each
+
+ ##
+ # Reads lines from the stream which are separated by +eol+.
+ #
+ # See also #gets
+
+ def readlines(eol=$/)
+ ary = []
+ while line = self.gets(eol)
+ ary << line
+ end
+ ary
+ end
+
+ ##
+ # Reads a line from the stream which is separated by +eol+.
+ #
+ # Raises EOFError if at end of file.
+
+ def readline(eol=$/)
+ raise EOFError if eof?
+ gets(eol)
+ end
+
+ ##
+ # Reads one character from the stream. Returns nil if called at end of
+ # file.
+
+ def getc
+ read(1)
+ end
+
+ ##
+ # Calls the given block once for each byte in the stream.
+
+ def each_byte # :yields: byte
+ while c = getc
+ yield(c.ord)
+ end
+ end
+
+ ##
+ # Reads a one-character string from the stream. Raises an EOFError at end
+ # of file.
+
+ def readchar
+ raise EOFError if eof?
+ getc
+ end
+
+ ##
+ # Pushes character +c+ back onto the stream such that a subsequent buffered
+ # character read will return it.
+ #
+ # Unlike IO#getc multiple bytes may be pushed back onto the stream.
+ #
+ # Has no effect on unbuffered reads (such as #sysread).
+
+ def ungetc(c)
+ @rbuffer[0,0] = c.chr
+ end
+
+ ##
+ # Returns true if the stream is at file which means there is no more data to
+ # be read.
+
+ def eof?
+ fill_rbuff if !@eof && @rbuffer.empty?
+ @eof && @rbuffer.empty?
+ end
+ alias eof eof?
+
+ #
+ # for writing.
+ #
+ private
+
+ ##
+ # Writes +s+ to the buffer. When the buffer is full or #sync is true the
+ # buffer is flushed to the underlying socket.
+
+ def do_write(s)
+ @wbuffer = "" unless defined? @wbuffer
+ @wbuffer << s
+ @sync ||= false
+ if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
+ remain = idx ? idx + $/.size : @wbuffer.length
+ nwritten = 0
+ while remain > 0
+ str = @wbuffer[nwritten,remain]
+ begin
+ nwrote = syswrite(str)
+ rescue Errno::EAGAIN
+ retry
+ end
+ remain -= nwrote
+ nwritten += nwrote
+ end
+ @wbuffer[0,nwritten] = ""
+ end
+ end
+
+ public
+
+ ##
+ # Writes +s+ to the stream. If the argument is not a string it will be
+ # converted using String#to_s. Returns the number of bytes written.
+
+ def write(s)
+ do_write(s)
+ s.length
+ end
+
+ ##
+ # Writes +str+ in the non-blocking manner.
+ #
+ # If there is buffered data, it is flushed first. This may block.
+ #
+ # write_nonblock returns number of bytes written to the SSL connection.
+ #
+ # When no data can be written without blocking it raises
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
+ #
+ # IO::WaitReadable means SSL needs to read internally so write_nonblock
+ # should be called again after the underlying IO is readable.
+ #
+ # IO::WaitWritable means SSL needs to write internally so write_nonblock
+ # should be called again after underlying IO is writable.
+ #
+ # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows.
+ #
+ # # emulates blocking write.
+ # begin
+ # result = ssl.write_nonblock(str)
+ # rescue IO::WaitReadable
+ # IO.select([io])
+ # retry
+ # rescue IO::WaitWritable
+ # IO.select(nil, [io])
+ # retry
+ # end
+ #
+ # Note that one reason that write_nonblock reads from the underlying IO
+ # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
+ # for more details. http://www.openssl.org/support/faq.html
+
+ def write_nonblock(s)
+ flush
+ syswrite_nonblock(s)
+ end
+
+ ##
+ # Writes +s+ to the stream. +s+ will be converted to a String using
+ # String#to_s.
+
+ def << (s)
+ do_write(s)
+ self
+ end
+
+ ##
+ # Writes +args+ to the stream along with a record separator.
+ #
+ # See IO#puts for full details.
+
+ def puts(*args)
+ s = ""
+ if args.empty?
+ s << "\n"
+ end
+ args.each{|arg|
+ s << arg.to_s
+ if $/ && /\n\z/ !~ s
+ s << "\n"
+ end
+ }
+ do_write(s)
+ nil
+ end
+
+ ##
+ # Writes +args+ to the stream.
+ #
+ # See IO#print for full details.
+
+ def print(*args)
+ s = ""
+ args.each{ |arg| s << arg.to_s }
+ do_write(s)
+ nil
+ end
+
+ ##
+ # Formats and writes to the stream converting parameters under control of
+ # the format string.
+ #
+ # See Kernel#sprintf for format string details.
+
+ def printf(s, *args)
+ do_write(s % args)
+ nil
+ end
+
+ ##
+ # Flushes buffered data to the SSLSocket.
+
+ def flush
+ osync = @sync
+ @sync = true
+ do_write ""
+ return self
+ ensure
+ @sync = osync
+ end
+
+ ##
+ # Closes the SSLSocket and flushes any unwritten data.
+
+ def close
+ flush rescue nil
+ sysclose
+ end
+end
View
65 lib/19/openssl/cipher.rb
@@ -0,0 +1,65 @@
+#--
+#
+# $RCSfile$
+#
+# = Ruby-space predefined Cipher subclasses
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licenced under the same licence as Ruby.
+# (See the file 'LICENCE'.)
+#
+# = Version
+# $Id: cipher.rb 33067 2011-08-25 00:52:10Z drbrain $
+#
+#++
+
+module OpenSSL
+ class Cipher
+ %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|*args|
+ cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
+ super(cipher_name)
+ }
+ }
+ const_set(name, klass)
+ }
+
+ %w(128 192 256).each{|keylen|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|mode|
+ mode ||= "CBC"
+ cipher_name = "AES-#{keylen}-#{mode}"
+ super(cipher_name)
+ }
+ }
+ const_set("AES#{keylen}", klass)
+ }
+
+ # Generate, set, and return a random key.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_key
+ str = OpenSSL::Random.random_bytes(self.key_len)
+ self.key = str
+ return str
+ end
+
+ # Generate, set, and return a random iv.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_iv
+ str = OpenSSL::Random.random_bytes(self.iv_len)
+ self.iv = str
+ return str
+ end
+
+ # This class is only provided for backwards compatibility. Use OpenSSL::Cipher in the future.
+ class Cipher < Cipher
+ # add warning
+ end
+ end # Cipher
+end # OpenSSL
View
313 lib/19/openssl/config.rb
@@ -0,0 +1,313 @@
+=begin
+= Ruby-space definitions that completes C-space funcs for Config
+
+= Info
+ Copyright (C) 2010 Hiroshi Nakamura <nahi@ruby-lang.org>
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+=end
+
+require 'stringio'
+
+module OpenSSL
+ class Config
+ include Enumerable
+
+ class << self
+ def parse(str)
+ c = new()
+ parse_config(StringIO.new(str)).each do |section, hash|
+ c[section] = hash
+ end
+ c
+ end
+
+ alias load new
+
+ def parse_config(io)
+ begin
+ parse_config_lines(io)
+ rescue ConfigError => e
+ e.message.replace("error in line #{io.lineno}: " + e.message)
+ raise
+ end
+ end
+
+ def get_key_string(data, section, key) # :nodoc:
+ if v = data[section] && data[section][key]
+ return v
+ elsif section == 'ENV'
+ if v = ENV[key]
+ return v
+ end
+ end
+ if v = data['default'] && data['default'][key]
+ return v
+ end
+ end
+
+ private
+
+ def parse_config_lines(io)
+ section = 'default'
+ data = {section => {}}
+ while definition = get_definition(io)
+ definition = clear_comments(definition)
+ next if definition.empty?
+ if definition[0] == ?[
+ 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
+ end
+ value = unescape_value(data, section, $3)
+ (data[section] ||= {})[key] = value.strip
+ else
+ raise ConfigError, "missing equal sign"
+ end
+ end
+ end
+ data
+ end
+
+ # escape with backslash
+ QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/
+ # escape with backslash and doubled dq
+ QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/
+ # escaped char map
+ ESCAPE_MAP = {
+ "r" => "\r",
+ "n" => "\n",
+ "b" => "\b",
+ "t" => "\t",
+ }
+
+ 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
+
+ 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
+
+ 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
+
+ def get_definition(io)
+ if line = get_line(io)
+ while /[^\\]\\\z/ =~ line
+ if extra = get_line(io)
+ line += extra
+ else
+ break
+ end
+ end
+ return line.strip
+ end
+ end
+
+ def get_line(io)
+ if line = io.gets
+ line.gsub(/[\r\n]*/, '')
+ end
+ end
+ end
+
+ def initialize(filename = nil)
+ @data = {}
+ if filename
+ File.open(filename.to_s) do |file|
+ Config.parse_config(file).each do |section, hash|
+ self[section] = hash
+ end
+ end
+ end
+ end
+
+ 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
+
+ def value(arg1, arg2 = nil)
+ warn('Config#value is deprecated; use Config#get_value')
+ if arg2.nil?
+ section, key = 'default', arg1
+ else
+ section, key = arg1, arg2
+ end
+ section ||= 'default'
+ section = 'default' if section.empty?
+ get_key_string(section, key)
+ end
+
+ def add_value(section, key, value)
+ check_modify
+ (@data[section] ||= {})[key] = value
+ end
+
+ def [](section)
+ @data[section] || {}
+ end
+
+ def section(name)
+ warn('Config#section is deprecated; use Config#[]')
+ @data[name] || {}
+ end
+
+ def []=(section, pairs)
+ check_modify
+ @data[section] ||= {}
+ pairs.each do |key, value|
+ self.add_value(section, key, value)
+ end
+ end
+
+ def sections
+ @data.keys
+ end
+
+ 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
+
+ def each
+ @data.each do |section, hash|
+ hash.each do |key, value|
+ yield [section, key, value]
+ end
+ end
+ end
+
+ def inspect
+ "#<#{self.class.name} sections=#{sections.inspect}>"
+ end
+
+ protected
+
+ def data
+ @data
+ end
+
+ private
+
+ def initialize_copy(other)
+ @data = other.data.dup
+ end
+
+ def check_modify
+ raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen?
+ end
+
+ def get_key_string(section, key)
+ Config.get_key_string(@data, section, key)
+ end
+ end
+end
View
72 lib/19/openssl/digest.rb
@@ -0,0 +1,72 @@
+#--
+#
+# $RCSfile$
+#
+# = Ruby-space predefined Digest subclasses
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licenced under the same licence as Ruby.
+# (See the file 'LICENCE'.)
+#
+# = Version
+# $Id: digest.rb 33067 2011-08-25 00:52:10Z drbrain $
+#
+#++
+
+module OpenSSL
+ class Digest
+
+ alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
+ if OPENSSL_VERSION_NUMBER > 0x00908000
+ alg += %w(SHA224 SHA256 SHA384 SHA512)
+ end
+
+ # Return the +data+ hash computed with +name+ Digest. +name+ is either the
+ # long name or short name of a supported digest algorithm.
+ #
+ # === Examples
+ #
+ # OpenSSL::Digest.digest("SHA256, "abc")
+ #
+ # which is equivalent to:
+ #
+ # OpenSSL::Digest::SHA256.digest("abc")
+
+ def self.digest(name, data)
+ super(data, name)
+ end
+
+ alg.each{|name|
+ klass = Class.new(Digest){
+ define_method(:initialize){|*data|
+ if data.length > 1
+ raise ArgumentError,
+ "wrong number of arguments (#{data.length} for 1)"
+ end
+ super(name, data.first)
+ }
+ }
+ singleton = (class << klass; self; end)
+ singleton.class_eval{
+ define_method(:digest){|data| Digest.digest(name, data) }
+ define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
+ }
+ const_set(name, klass)
+ }
+
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
+ class Digest < Digest
+ def initialize(*args)
+ # add warning
+ super(*args)
+ end
+ end
+
+ end # Digest
+end # OpenSSL
+
View
3 lib/19/openssl/ext/.gitignore
@@ -0,0 +1,3 @@
+extconf.h
+mkmf.log
+Makefile
View
140 lib/19/openssl/ext/extconf.rb
@@ -0,0 +1,140 @@
+=begin
+= $RCSfile$ -- Generator for Makefile
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: extconf.rb 32230 2011-06-26 01:32:03Z emboss $
+=end
+
+require "mkmf"
+
+dir_config("openssl")
+dir_config("kerberos")
+
+message "=== OpenSSL for Ruby configurator ===\n"
+
+##
+# Adds -Wall -DOSSL_DEBUG for compilation and some more targets when GCC is used
+# To turn it on, use: --with-debug or --enable-debug
+#
+if with_config("debug") or enable_config("debug")
+ $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
+
+ if CONFIG['GCC'] == 'yes'
+ $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
+ end
+end
+
+message "=== Checking for system dependent stuff... ===\n"
+have_library("nsl", "t_open")
+have_library("socket", "socket")
+have_header("assert.h")
+
+message "=== Checking for required stuff... ===\n"
+if $mingw
+ have_library("wsock32")
+ have_library("gdi32")
+end
+
+result = pkg_config("openssl") && have_header("openssl/ssl.h")
+
+unless result
+ result = have_header("openssl/ssl.h")
+ result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
+ result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")}
+ unless result
+ message "=== Checking for required stuff failed. ===\n"
+ message "Makefile wasn't created. Fix the errors above.\n"
+ exit 1
+ end
+end
+
+unless have_header("openssl/conf_api.h")
+ message "OpenSSL 0.9.6 or later required.\n"
+ exit 1
+end
+
+%w"rb_str_set_len rb_block_call".each {|func| have_func(func, "ruby.h")}
+
+message "=== Checking for OpenSSL features... ===\n"
+have_func("ERR_peek_last_error")
+have_func("ASN1_put_eoc")
+have_func("BN_mod_add")
+have_func("BN_mod_sqr")
+have_func("BN_mod_sub")
+have_func("BN_pseudo_rand_range")
+have_func("BN_rand_range")
+have_func("CONF_get1_default_config_file")
+have_func("EVP_CIPHER_CTX_copy")
+have_func("EVP_CIPHER_CTX_set_padding")
+have_func("EVP_CipherFinal_ex")
+have_func("EVP_CipherInit_ex")
+have_func("EVP_DigestFinal_ex")
+have_func("EVP_DigestInit_ex")
+have_func("EVP_MD_CTX_cleanup")
+have_func("EVP_MD_CTX_create")
+have_func("EVP_MD_CTX_destroy")
+have_func("EVP_MD_CTX_init")
+have_func("HMAC_CTX_cleanup")
+have_func("HMAC_CTX_copy")
+have_func("HMAC_CTX_init")
+have_func("PEM_def_callback")
+have_func("PKCS5_PBKDF2_HMAC")
+have_func("PKCS5_PBKDF2_HMAC_SHA1")
+have_func("X509V3_set_nconf")
+have_func("X509V3_EXT_nconf_nid")
+have_func("X509_CRL_add0_revoked")
+have_func("X509_CRL_set_issuer_name")
+have_func("X509_CRL_set_version")
+have_func("X509_CRL_sort")
+have_func("X509_NAME_hash_old")
+have_func("X509_STORE_get_ex_data")
+have_func("X509_STORE_set_ex_data")
+have_func("OBJ_NAME_do_all_sorted")
+have_func("SSL_SESSION_get_id")
+have_func("SSL_SESSION_cmp")
+have_func("OPENSSL_cleanse")
+have_func("SSLv2_method")
+have_func("SSLv2_server_method")
+have_func("SSLv2_client_method")
+unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h'])
+ have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME")
+end
+if have_header("openssl/engine.h")
+ have_func("ENGINE_add")
+ have_func("ENGINE_load_builtin_engines")
+ have_func("ENGINE_load_openbsd_dev_crypto")
+ have_func("ENGINE_get_digest")
+ have_func("ENGINE_get_cipher")
+ have_func("ENGINE_cleanup")
+ have_func("ENGINE_load_4758cca")
+ have_func("ENGINE_load_aep")
+ have_func("ENGINE_load_atalla")
+ have_func("ENGINE_load_chil")
+ have_func("ENGINE_load_cswift")
+ have_func("ENGINE_load_nuron")
+ have_func("ENGINE_load_sureware")
+ have_func("ENGINE_load_ubsec")
+end
+if checking_for('OpenSSL version is 0.9.7 or later') {
+ try_static_assert('OPENSSL_VERSION_NUMBER >= 0x00907000L', 'openssl/opensslv.h')
+ }
+ have_header("openssl/ocsp.h")
+end
+have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
+have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
+have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
+
+message "=== Checking done. ===\n"
+
+create_header
+create_makefile("openssl")
+message "Done.\n"
View
356 lib/19/openssl/ext/openssl_missing.c
@@ -0,0 +1,356 @@
+/*
+ * $Id: openssl_missing.c 32230 2011-06-26 01:32:03Z emboss $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include RUBY_EXTCONF_H
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
+# include <openssl/engine.h>
+#endif
+#include <openssl/x509_vfy.h>
+
+#if !defined(OPENSSL_NO_HMAC)
+#include <string.h> /* memcpy() */
+#include <openssl/hmac.h>
+
+#include "openssl_missing.h"
+
+#if !defined(HAVE_HMAC_CTX_COPY)
+void
+HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
+{
+ if (!out || !in) return;
+ memcpy(out, in, sizeof(HMAC_CTX));
+
+ EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
+ EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
+ EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
+}
+#endif /* HAVE_HMAC_CTX_COPY */
+#endif /* NO_HMAC */
+
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
+int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
+{
+ return CRYPTO_set_ex_data(&str->ex_data, idx, data);
+}
+#endif
+
+#if !defined(HAVE_X509_STORE_GET_EX_DATA)
+void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
+{
+ return CRYPTO_get_ex_data(&str->ex_data, idx);
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CREATE)
+EVP_MD_CTX *
+EVP_MD_CTX_create(void)
+{
+ EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
+ if (!ctx) return NULL;
+
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+
+ return ctx;
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
+int
+EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
+{
+ /* FIXME!!! */
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_DESTROY)
+void
+EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
+{
+ EVP_MD_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_INIT)
+void
+EVP_MD_CTX_init(EVP_MD_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+}
+#endif
+
+#if !defined(HAVE_HMAC_CTX_INIT)
+void
+HMAC_CTX_init(HMAC_CTX *ctx)
+{
+ EVP_MD_CTX_init(&ctx->i_ctx);
+ EVP_MD_CTX_init(&ctx->o_ctx);
+ EVP_MD_CTX_init(&ctx->md_ctx);
+}
+#endif
+
+#if !defined(HAVE_HMAC_CTX_CLEANUP)
+void
+HMAC_CTX_cleanup(HMAC_CTX *ctx)
+{
+ EVP_MD_CTX_cleanup(&ctx->i_ctx);
+ EVP_MD_CTX_cleanup(&ctx->o_ctx);
+ EVP_MD_CTX_cleanup(&ctx->md_ctx);
+ memset(ctx, 0, sizeof(HMAC_CTX));
+}
+#endif
+
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+/*
+ * this function does not exist in OpenSSL yet... or ever?.
+ * a future version may break this function.
+ * tested on 0.9.7d.
+ */
+int
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
+{
+ memcpy(out, in, sizeof(EVP_CIPHER_CTX));
+
+#if defined(HAVE_ENGINE_ADD) && defined(HAVE_ST_ENGINE)
+ if (in->engine) ENGINE_add(out->engine);
+ if (in->cipher_data) {
+ out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
+ memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+ }
+#endif
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_VERSION)
+int
+X509_CRL_set_version(X509_CRL *x, long version)
+{
+ if (x == NULL || x->crl == NULL) return 0;
+ if (x->crl->version == NULL) {
+ x->crl->version = M_ASN1_INTEGER_new();
+ if (x->crl->version == NULL) return 0;
+ }
+ return ASN1_INTEGER_set(x->crl->version, version);
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
+int
+X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
+{
+ if (x == NULL || x->crl == NULL) return 0;
+ return X509_NAME_set(&x->crl->issuer, name);
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SORT)
+int
+X509_CRL_sort(X509_CRL *c)
+{
+ int i;
+ X509_REVOKED *r;
+ /* sort the data so it will be written in serial
+ * number order */
+ sk_X509_REVOKED_sort(c->crl->revoked);
+ for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) {
+ r=sk_X509_REVOKED_value(c->crl->revoked, i);
+ r->sequence=i;
+ }
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
+static int
+OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
+{
+ return(ASN1_STRING_cmp(
+ (ASN1_STRING *)(*a)->serialNumber,
+ (ASN1_STRING *)(*b)->serialNumber));
+}
+
+int
+X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
+{
+ X509_CRL_INFO *inf;
+
+ inf = crl->crl;
+ if (!inf->revoked)
+ inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
+ if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev))
+ return 0;
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_SQR)
+int
+BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0;
+ return BN_mod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB)
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
+{
+ if (!BN_mod(r,m,d,ctx)) return 0;
+ if (!r->neg) return 1;
+ return (d->neg ? BN_sub : BN_add)(r, r, d);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD)
+int
+BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_add(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_SUB)
+int
+BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_sub(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE)
+static int
+bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
+{
+ int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
+ int n;
+
+ if (range->neg || BN_is_zero(range)) return 0;
+
+ n = BN_num_bits(range);
+
+ if (n == 1) {
+ if (!BN_zero(r)) return 0;
+ } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
+ do {
+ if (!bn_rand(r, n + 1, -1, 0)) return 0;
+ if (BN_cmp(r ,range) >= 0) {
+ if (!BN_sub(r, r, range)) return 0;
+ if (BN_cmp(r, range) >= 0)
+ if (!BN_sub(r, r, range)) return 0;
+ }
+ } while (BN_cmp(r, range) >= 0);
+ } else {
+ do {
+ if (!bn_rand(r, n, -1, 0)) return 0;
+ } while (BN_cmp(r, range) >= 0);
+ }
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE)
+int
+BN_rand_range(BIGNUM *r, BIGNUM *range)
+{
+ return bn_rand_range(0, r, range);
+}
+#endif
+
+#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
+int
+BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
+{
+ return bn_rand_range(1, r, range);
+}
+#endif
+
+#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
+#define OPENSSL_CONF "openssl.cnf"
+char *
+CONF_get1_default_config_file(void)
+{
+ char *file;
+ int len;
+
+ file = getenv("OPENSSL_CONF");
+ if (file) return BUF_strdup(file);
+ len = strlen(X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+ len++;
+#endif
+ len += strlen(OPENSSL_CONF);
+ file = OPENSSL_malloc(len + 1);
+ if (!file) return NULL;
+ strcpy(file,X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+ strcat(file,"/");
+#endif
+ strcat(file,OPENSSL_CONF);
+
+ return file;
+}
+#endif
+
+#if !defined(HAVE_PEM_DEF_CALLBACK)
+#define OSSL_PASS_MIN_LENGTH 4
+int
+PEM_def_callback(char *buf, int num, int w, void *key)
+{
+ int i,j;
+ const char *prompt;
+
+ if (key) {
+ i = strlen(key);
+ i = (i > num) ? num : i;
+ memcpy(buf, key, i);
+ return i;
+ }
+
+ prompt = EVP_get_pw_prompt();
+ if (prompt == NULL) prompt = "Enter PEM pass phrase:";
+ for (;;) {
+ i = EVP_read_pw_string(buf, num, prompt, w);
+ if (i != 0) {
+ memset(buf, 0, (unsigned int)num);
+ return(-1);
+ }
+ j = strlen(buf);
+ if (j < OSSL_PASS_MIN_LENGTH) {
+ fprintf(stderr,
+ "phrase is too short, needs to be at least %d chars\n",
+ OSSL_PASS_MIN_LENGTH);
+ }
+ else break;
+ }
+ return j;
+}
+#endif
+
+#if !defined(HAVE_ASN1_PUT_EOC)
+int
+ASN1_put_eoc(unsigned char **pp)
+{
+ unsigned char *p = *pp;
+ *p++ = 0;
+ *p++ = 0;
+ *pp = p;
+ return 2;
+}
+#endif
+
View
198 lib/19/openssl/ext/openssl_missing.h
@@ -0,0 +1,198 @@
+/*
+ * $Id: openssl_missing.h 32230 2011-06-26 01:32:03Z emboss $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#if !defined(_OSSL_OPENSSL_MISSING_H_)
+#define _OSSL_OPENSSL_MISSING_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef TYPEDEF_D2I_OF
+typedef char *d2i_of_void();
+#endif
+#ifndef TYPEDEF_I2D_OF
+typedef int i2d_of_void();
+#endif
+
+/*
+ * These functions are not included in headers of OPENSSL <= 0.9.6b
+ */
+
+#if !defined(PEM_read_bio_DSAPublicKey)
+# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (d2i_of_void *)d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,(bp),(void **)(x),(cb),(u))
+#endif
+
+#if !defined(PEM_write_bio_DSAPublicKey)
+# define PEM_write_bio_DSAPublicKey(bp,x) \
+ PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPublicKey,\
+ PEM_STRING_DSA_PUBLIC,\
+ (bp),(char *)(x), NULL, NULL, 0, NULL, NULL)
+#endif
+
+#if !defined(DSAPrivateKey_dup)
+# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, \
+ (d2i_of_void *)d2i_DSAPrivateKey,(char *)(dsa))
+#endif
+
+#if !defined(DSAPublicKey_dup)
+# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPublicKey, \
+ (d2i_of_void *)d2i_DSAPublicKey,(char *)(dsa))
+#endif
+
+#if !defined(X509_REVOKED_dup)
+# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \
+ (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev))
+#endif
+
+#if !defined(PKCS7_SIGNER_INFO_dup)
+# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, \
+ (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, (char *)(si))
+#endif
+
+#if !defined(PKCS7_RECIP_INFO_dup)
+# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, \
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO, (char *)(ri))
+#endif
+
+#if !defined(HAVE_HMAC_CTX_INIT)
+void HMAC_CTX_init(HMAC_CTX *ctx);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_COPY)
+void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_CLEANUP)
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CREATE)
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_INIT)
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_DESTROY)
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
+#endif
+
+#if !defined(HAVE_EVP_DIGESTINIT_EX)
+# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit((ctx), (md))
+#endif
+#if !defined(HAVE_EVP_DIGESTFINAL_EX)
+# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal((ctx), (buf), (len))
+#endif
+
+#if !defined(HAVE_EVP_CIPHERINIT_EX)
+# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit((ctx), (type), (key), (iv), (enc))
+#endif
+#if !defined(HAVE_EVP_CIPHERFINAL_EX)
+# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal((ctx), (outm), (outl))
+#endif
+
+#if !defined(EVP_CIPHER_name)
+# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
+#endif
+
+#if !defined(EVP_MD_name)
+# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
+#endif
+
+#if !defined(HAVE_EVP_HMAC_INIT_EX)
+# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init((ctx), (key), (len), (digest))
+#endif
+
+#if !defined(PKCS7_is_detached)
+# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+#endif
+
+#if !defined(PKCS7_type_is_encrypted)
+# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+#endif
+
+#if !defined(HAVE_OPENSSL_CLEANSE)
+#define OPENSSL_cleanse(p, l) memset((p), 0, (l))
+#endif
+
+#if !defined(HAVE_X509_STORE_GET_EX_DATA)
+void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
+#endif
+
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
+int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_VERSION)
+int X509_CRL_set_version(X509_CRL *x, long version);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+#endif
+
+#if !defined(HAVE_X509_CRL_SORT)
+int X509_CRL_sort(X509_CRL *c);
+#endif
+
+#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+#endif
+
+#if !defined(HAVE_BN_MOD_SQR)
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD)
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_SUB)
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE)
+int BN_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
+int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
+char *CONF_get1_default_config_file(void);
+#endif
+
+#if !defined(HAVE_PEM_DEF_CALLBACK)
+int PEM_def_callback(char *buf, int num, int w, void *key);
+#endif
+
+#if !defined(HAVE_ASN1_PUT_EOC)
+int ASN1_put_eoc(unsigned char **pp);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* _OSSL_OPENSSL_MISSING_H_ */
+
View
901 lib/19/openssl/ext/ossl.c
@@ -0,0 +1,901 @@
+/*
+ * $Id: ossl.c 32538 2011-07-14 05:46:00Z nahi $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+#include <stdarg.h> /* for ossl_raise */
+
+/*
+ * String to HEXString conversion
+ */
+int
+string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
+{
+ static const char hex[]="0123456789abcdef";
+ int i, len = 2 * buf_len;
+
+ if (buf_len < 0 || len < buf_len) { /* PARANOIA? */
+ return -1;
+ }
+ if (!hexbuf) { /* if no buf, return calculated len */
+ if (hexbuf_len) {
+ *hexbuf_len = len;
+ }
+ return len;
+ }
+ if (!(*hexbuf = OPENSSL_malloc(len + 1))) {
+ return -1;
+ }
+ for (i = 0; i < buf_len; i++) {
+ (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4];
+ (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f];
+ }
+ (*hexbuf)[2 * i] = '\0';
+
+ if (hexbuf_len) {
+ *hexbuf_len = len;
+ }
+ return len;
+}
+
+/*
+ * Data Conversion
+ */
+#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
+STACK_OF(type) * \
+ossl_##name##_ary2sk0(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ VALUE val; \
+ type *x; \
+ int i; \
+ \
+ Check_Type(ary, T_ARRAY); \
+ sk = sk_##type##_new_null(); \
+ if (!sk) ossl_raise(eOSSLError, NULL); \
+ \
+ for (i = 0; i < RARRAY_LEN(ary); i++) { \
+ val = rb_ary_entry(ary, i); \
+ if (!rb_obj_is_kind_of(val, expected_class)) { \
+ sk_##type##_pop_free(sk, type##_free); \
+ ossl_raise(eOSSLError, "object in array not" \
+ " of class ##type##"); \
+ } \
+ x = dup(val); /* NEED TO DUP */ \
+ sk_##type##_push(sk, x); \
+ } \
+ return sk; \
+} \
+ \
+STACK_OF(type) * \
+ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
+{ \
+ return (STACK_OF(type)*)rb_protect( \
+ (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \
+ ary, \
+ status); \
+} \
+ \
+STACK_OF(type) * \
+ossl_##name##_ary2sk(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ int status = 0; \
+ \
+ sk = ossl_protect_##name##_ary2sk(ary, &status); \
+ if (status) rb_jump_tag(status); \
+ \
+ return sk; \
+}
+OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
+
+#define OSSL_IMPL_SK2ARY(name, type) \
+VALUE \
+ossl_##name##_sk2ary(STACK_OF(type) *sk) \
+{ \
+ type *t; \
+ int i, num; \
+ VALUE ary; \
+ \
+ if (!sk) { \
+ OSSL_Debug("empty sk!"); \
+ return Qnil; \
+ } \
+ num = sk_##type##_num(sk); \
+ if (num < 0) { \
+ OSSL_Debug("items in sk < -1???"); \
+ return rb_ary_new(); \
+ } \
+ ary = rb_ary_new2(num); \
+ \
+ for (i=0; i<num; i++) { \
+ t = sk_##type##_value(sk, i); \
+ rb_ary_push(ary, ossl_##name##_new(t)); \
+ } \
+ return ary; \
+}
+OSSL_IMPL_SK2ARY(x509, X509)
+OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
+OSSL_IMPL_SK2ARY(x509name, X509_NAME)
+
+static VALUE
+ossl_str_new(int size)
+{
+ return rb_str_new(0, size);
+}
+
+VALUE
+ossl_buf2str(char *buf, int len)
+{
+ VALUE str;
+ int status = 0;
+
+ str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
+ if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
+ OPENSSL_free(buf);
+ if(status) rb_jump_tag(status);
+
+ return str;
+}
+
+/*
+ * our default PEM callback
+ */
+static VALUE
+ossl_pem_passwd_cb0(VALUE flag)
+{
+ VALUE pass;
+
+ pass = rb_yield(flag);
+ SafeStringValue(pass);
+
+ return pass;
+}
+
+int
+ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
+{
+ int len, status = 0;
+ VALUE rflag, pass;
+
+ if (pwd || !rb_block_given_p())
+ return PEM_def_callback(buf, max_len, flag, pwd);
+
+ while (1) {
+ /*
+ * when the flag is nonzero, this passphrase
+ * will be used to perform encryption; otherwise it will
+ * be used to perform decryption.
+ */
+ rflag = flag ? Qtrue : Qfalse;
+ pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
+ if (status) return -1; /* exception was raised. */
+ len = RSTRING_LENINT(pass);
+ if (len < 4) { /* 4 is OpenSSL hardcoded limit */
+ rb_warning("password must be longer than 4 bytes");
+ continue;
+ }
+ if (len > max_len) {
+ rb_warning("password must be shorter then %d bytes", max_len-1);
+ continue;
+ }
+ memcpy(buf, RSTRING_PTR(pass), len);
+ break;
+ }
+ return len;
+}
+
+/*
+ * Verify callback
+ */
+int ossl_verify_cb_idx;
+
+VALUE
+ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
+{
+ return rb_funcall(args->proc, rb_intern("call"), 2,
+ args->preverify_ok, args->store_ctx);
+}
+
+int
+ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ VALUE proc, rctx, ret;
+ struct ossl_verify_cb_args args;
+ int state = 0;
+
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx);
+ if ((void*)proc == 0)
+ proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx);
+ if ((void*)proc == 0)
+ return ok;
+ if (!NIL_P(proc)) {
+ rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
+ (VALUE)ctx, &state);
+ ret = Qfalse;
+ if (!state) {
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
+ ossl_x509stctx_clear_ptr(rctx);
+ if (state) {
+ rb_warn("exception in verify_callback is ignored");
+ }
+ }
+ if (ret == Qtrue) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ }
+ else{
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) {
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ }
+ ok = 0;
+ }
+ }
+
+ return ok;
+}
+
+/*
+ * main module
+ */
+VALUE mOSSL;
+
+/*
+ * OpenSSLError < StandardError
+ */
+VALUE eOSSLError;
+
+/*
+ * Convert to DER string
+ */
+ID ossl_s_to_der;
+
+VALUE
+ossl_to_der(VALUE obj)
+{
+ VALUE tmp;
+
+ tmp = rb_funcall(obj, ossl_s_to_der, 0);
+ StringValue(tmp);
+
+ return tmp;
+}
+
+VALUE
+ossl_to_der_if_possible(VALUE obj)
+{
+ if(rb_respond_to(obj, ossl_s_to_der))
+ return ossl_to_der(obj);
+ return obj;
+}
+
+/*
+ * Errors
+ */
+static VALUE
+ossl_make_error(VALUE exc, const char *fmt, va_list args)
+{
+ char buf[BUFSIZ];
+ const char *msg;
+ long e;
+ int len = 0;
+
+#ifdef HAVE_ERR_PEEK_LAST_ERROR
+ e = ERR_peek_last_error();
+#else
+ e = ERR_peek_error();
+#endif
+ if (fmt) {
+ len = vsnprintf(buf, BUFSIZ, fmt, args);
+ }
+ if (len < BUFSIZ && e) {
+ if (dOSSL == Qtrue) /* FULL INFO */
+ msg = ERR_error_string(e, NULL);
+ else
+ msg = ERR_reason_error_string(e);
+ len += snprintf(buf+len, BUFSIZ-len, "%s%s", (len ? ": " : ""), msg);
+ }
+ if (dOSSL == Qtrue){ /* show all errors on the stack */
+ while ((e = ERR_get_error()) != 0){
+ rb_warn("error on stack: %s", ERR_error_string(e, NULL));
+ }
+ }
+ ERR_clear_error();
+
+ if(len > BUFSIZ) len = rb_long2int(strlen(buf));
+ return rb_exc_new(exc, buf, len);
+}
+
+void
+ossl_raise(VALUE exc, const char *fmt, ...)
+{
+ va_list args;
+ VALUE err;
+ va_start(args, fmt);
+ err = ossl_make_error(exc, fmt, args);
+ va_end(args);
+ rb_exc_raise(err);
+}
+
+VALUE
+ossl_exc_new(VALUE exc, const char *fmt, ...)
+{
+ va_list args;
+ VALUE err;
+ va_start(args, fmt);
+ err = ossl_make_error(exc, fmt, args);
+ va_end(args);
+ return err;
+}
+
+/*
+ * call-seq:
+ * OpenSSL.errors -> [String...]
+ *
+ * See any remaining errors held in queue.
+ *
+ * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
+ */
+VALUE
+ossl_get_errors()
+{
+ VALUE ary;
+ long e;
+
+ ary = rb_ary_new();
+ while ((e = ERR_get_error()) != 0){
+ rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL)));
+ }
+
+ return ary;
+}
+
+/*
+ * Debug
+ */
+VALUE dOSSL;
+
+#if !defined(HAVE_VA_ARGS_MACRO)
+void
+ossl_debug(const char *fmt, ...)
+{
+ va_list args;
+
+ if (dOSSL == Qtrue) {
+ fprintf(stderr, "OSSL_DEBUG: ");
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, " [CONTEXT N/A]\n");
+ }
+}
+#endif
+
+/*
+ * call-seq:
+ * OpenSSL.debug -> true | false
+ */
+static VALUE
+ossl_debug_get(VALUE self)
+{
+ return dOSSL;
+}
+
+/*
+ * call-seq:
+ * OpenSSL.debug = boolean -> boolean
+ *
+ * Turns on or off CRYPTO_MEM_CHECK.
+ * Also shows some debugging message on stderr.
+ */
+static VALUE
+ossl_debug_set(VALUE self, VALUE val)
+{
+ VALUE old = dOSSL;
+ dOSSL = val;
+
+ if (old != dOSSL) {
+ if (dOSSL == Qtrue) {
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+ fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n");
+ } else if (old == Qtrue) {
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
+ fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n");
+ }
+ }
+ return val;
+}
+
+/*
+ * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
+ * OpenSSL[http://www.openssl.org/] library.
+ *
+ * = Examples
+ *
+ * All examples assume you have loaded OpenSSL with:
+ *
+ * require 'openssl'
+ *
+ * These examples build atop each other. For example the key created in the
+ * next is used in throughout these examples.
+ *
+ * == Keys
+ *
+ * === Creating a Key
+ *
+ * This example creates a 2048 bit RSA keypair and writes it to the current
+ * directory.
+ *
+ * key = OpenSSL::PKey::RSA.new 2048
+ *
+ * open 'private_key.pem', 'w' do |io| io.write key.to_pem end
+ * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
+ *
+ * === Exporting a Key
+ *
+ * Keys saved to disk without encryption are not secure as anyone who gets
+ * ahold of the key may use it unless it is encrypted. In order to securely
+ * export a key you may export it with a pass phrase.
+ *
+ * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ * pass_phrase = 'my secure pass phrase goes here'
+ *
+ * key_secure = key.export cipher, pass_phrase
+ *
+ * open 'private.secure.pem', 'w' do |io|
+ * io.write key_secure
+ * end
+ *
+ * OpenSSL::Cipher.ciphers returns a list of available ciphers.
+ *
+ * === Loading a Key
+ *
+ * A key can also be loaded from a file.
+ *
+ * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
+ * key2.public? # => true
+ *
+ * or
+ *
+ * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
+ * key3.private? # => false
+ *
+ * === Loading an Encrypted Key
+ *
+ * OpenSSL will prompt you for your pass phrase when loading an encrypted key.
+ * If you will not be able to type in the pass phrase you may provide it when
+ * loading the key:
+ *
+ * key4_pem = File.read 'private.secure.pem'
+ * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
+ *
+ * == RSA Encryption
+ *
+ * RSA provides ecryption and decryption using the public and private keys.
+ * You can use a variety of padding methods depending upon the intended use of
+ * encrypted data.
+ *
+ * === Encryption
+ *
+ * Documents encrypted with the public key can only be decrypted with the
+ * private key.
+ *
+ * public_encrypted = key.public_encrypt 'top secret document'
+ *
+ * Documents encrypted with the private key can only be decrypted with the
+ * public key.
+ *
+ * private_encrypted = key.private_encrypt 'public release document'
+ *
+ * === Decryption
+ *
+ * Use the opposite key type do decrypt the document
+ *
+ * top_secret = key.public_decrypt public_encrypted
+ *
+ * public_release = key.private_decrypt private_encrypted
+ *
+ * == PKCS #5 Password-based Encryption
+ *
+ * PKCS #5 is a password-based encryption standard documented at
+ * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or
+ * passphrase to be used to create a secure encryption key.
+ *
+ * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
+ * key.
+ *
+ * pass_phrase = 'my secure pass phrase goes here'
+ * salt = '8 octets'
+ *
+ * === Encryption
+ *
+ * First set up the cipher for encryption
+ *
+ * encrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ * encrypter.encrypt
+ * encrypter.pkcs5_keyivgen pass_phrase, salt
+ *
+ * Then pass the data you want to encrypt through
+ *
+ * encrypted = encrypter.update 'top secret document'
+ * encrypted << encrypter.final
+ *
+ * === Decryption
+ *
+ * Use a new Cipher instance set up for decryption
+ *
+ * decrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ * decrypter.decrypt
+ * decrypter.pkcs5_keyivgen pass_phrase, salt
+ *
+ * Then pass the data you want to decrypt through
+ *
+ * plain = decrypter.update encrypted
+ * plain << decrypter.final
+ *
+ * == X509 Certificates
+ *
+ * === Creating a Certificate
+ *
+ * This example creates a self-signed certificate using an RSA key and a SHA1
+ * signature.
+ *
+ * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
+ *
+ * cert = OpenSSL::X509::Certificate.new
+ * cert.version = 2
+ * cert.serial = 0
+ * cert.not_before = Time.now
+ * cert.not_after = Time.now + 3600
+ *
+ * cert.public_key = key.public_key
+ * cert.subject = name
+ *
+ * === Certificate Extensions
+ *
+ * You can add extensions to the certificate with
+ * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
+ *
+ * extension_factory.create_extension 'basicConstraints', 'CA:FALSE'
+ * extension_factory.create_extension 'keyUsage',
+ * 'keyEncipherment,dataEncipherment,digitalSignature'
+ * extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
+ *
+ * === Signing a Certificate
+ *
+ * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
+ * with a digest algorithm. This creates a self-signed cert because we're using
+ * the same name and key to sign the certificate as was used to create the
+ * certificate.
+ *
+ * cert.issuer = name
+ * cert.sign key, OpenSSL::Digest::SHA1.new
+ *
+ * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
+ *
+ * === Loading a Certificate
+ *
+ * Like a key, a cert can also be loaded from a file.
+ *
+ * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
+ *
+ * === Verifying a Certificate
+ *
+ * Certificate#verify will return true when a certificate was signed with the
+ * given public key.
+ *
+ * raise 'certificate can not be verified' unless cert2.verify key
+ *
+ * == Certificate Authority
+ *
+ * A certificate authority (CA) is a trusted third party that allows you to
+ * verify the ownership of unknown certificates. The CA issues key signatures
+ * that indicate it trusts the user of that key. A user encountering the key
+ * can verify the signature by using the CA's public key.
+ *
+ * === CA Key
+ *
+ * CA keys are valuable, so we encrypt and save it to disk and make sure it is
+ * not readable by other users.
+ *
+ * ca_key = OpenSSL::PKey::RSA.new 2048
+ *
+ * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ *
+ * open 'ca_key.pem', 'w', 0400 do |io|
+ * io.write key.export(cipher, pass_phrase)
+ * end
+ *
+ * === CA Certificate
+ *
+ * A CA certificate is created the same way we created a certificate above, but
+ * with different extensions.
+ *
+ * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
+ *
+ * ca_cert = OpenSSL::X509::Certificate.new
+ * ca_cert.serial = 0
+ * ca_cert.version = 2
+ * ca_cert.not_before = Time.now
+ * ca_cert.not_after = Time.now + 86400
+ *
+ * ca_cert.public_key = ca_key.public_key
+ * ca_cert.subject = ca_name
+ * ca_cert.issuer = ca_name
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
+ * extension_factory.subject_certificate = ca_cert
+ * extension_factory.issuer_certificate = ca_cert
+ *
+ * extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
+ *
+ * This extension indicates the CA's key may be used as a CA.
+ *
+ * extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true
+ *
+ * This extension indicates the CA's key may be used to verify signatures on
+ * both certificates and certificate revocations.
+ *
+ * extension_factory.create_extension 'keyUsage', 'cRLSign,keyCertSign', true
+ *
+ * Root CA certificates are self-signed.
+ *
+ * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
+ *
+ * The CA certificate is saved to disk so it may be distributed to all the
+ * users of the keys this CA will sign.
+ *
+ * open 'ca_cert.pem', 'w' do |io|
+ * io.write ca_cert.to_pem
+ * end
+ *
+ * === Certificate Signing Request
+ *
+ * The CA signs keys through a Certificate Signing Request (CSR). The CSR
+ * contains the information necessary to identify the key.
+ *
+ * csr = OpenSSL::X509::Request.new
+ * csr.version = 0
+ * csr.subject = name
+ * csr.public_key = key.public_key
+ * csr.sign key, OpenSSL::Digest::SHA1.new
+ *
+ * A CSR is saved to disk and sent to the CA for signing.
+ *
+ * open 'csr.pem', 'w' do |io|
+ * io.write csr.to_pem
+ * end
+ *
+ * === Creating a Certificate from a CSR
+ *
+ * Upon receiving a CSR the CA will verify it before signing it. A minimal
+ * verification would be to check the CSR's signature.
+ *
+ * csr = OpenSSL::X509::Request.new File.read 'csr.pem'
+ *
+ * raise 'CSR can not be verified' unless csr.verify csr.public_key
+ *
+ * After verification a certificate is created, marked for various usages,
+ * signed with the CA key and returned to the requester.
+ *
+ * csr_cert = OpenSSL::X509::Certificate.new
+ * csr_cert.serial = 0
+ * csr_cert.version = 2
+ * csr_cert.not_before = Time.now
+ * csr_cert.not_after = Time.now + 600
+ *
+ * csr_cert.subject = csr.subject
+ * csr_cert.public_key = csr.public_key
+ * csr_cert.issuer = ca_cert.subject
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
+ * extension_factory.subject_certificate = csr_cert
+ * extension_factory.issuer_certificate = ca_cert
+ *
+ * extension_factory.create_extension 'basicConstraints', 'CA:FALSE'
+ * extension_factory.create_extension 'keyUsage',
+ * 'keyEncipherment,dataEncipherment,digitalSignature'
+ * extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
+ *
+ * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
+ *
+ * open 'csr_cert.pem', 'w' do |io|
+ * io.write csr_cert.to_pem
+ * end
+ *
+ * == SSL and TLS Connections
+ *
+ * Using our created key and certificate we can create an SSL or TLS connection.
+ * An SSLContext is used to set up an SSL session.
+ *
+ * context = OpenSSL::SSL::SSLContext.new
+ *
+ * === SSL Server
+ *
+ * An SSL server requires the certificate and private key to communicate
+ * securely with its clients:
+ *
+ * context.cert = cert
+ * context.key = key
+ *
+ * Then create an SSLServer with a TCP server socket and the context. Use the
+ * SSLServer like an ordinary TCP server.
+ *
+ * require 'socket'
+ *
+ * tcp_server = TCPServer.new 5000
+ * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
+ *
+ * loop do
+ * ssl_connection = ssl_server.accept
+ *
+ * data = connection.gets
+ *
+ * response = "I got #{data.dump}"
+ * puts response
+ *
+ * connection.puts "I got #{data.dump}"
+ * connection.close
+ * end
+ *
+ * === SSL client
+ *
+ * An SSL client is created with a TCP socket and the context.
+ * SSLSocket#connect must be called to initiate the SSL handshake and start
+ * encryption. A key and certificate are not required for the client socket.
+ *
+ * require 'socket'
+ *
+ * tcp_client = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
+ * ssl_client.connect
+ *
+ * ssl_client.puts "hello server!"
+ * puts ssl_client.gets
+ *
+ * === Peer Verification
+ *
+ * An unverified SSL connection does not provide much security. For enhanced
+ * security the client or server can verify the certificate of its peer.
+ *
+ * The client can be modified to verify the server's certificate against the
+ * certificate authority's certificate:
+ *
+ * context.ca_file = 'ca_cert.pem'
+ * context.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ *
+ * require 'socket'
+ *
+ * tcp_client = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
+ * ssl_client.connect
+ *
+ * ssl_client.puts "hello server!"
+ * puts ssl_client.gets
+ *