From 6175ca03be6d0d51359f9017123708987d0f5eb7 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Wed, 15 Aug 2007 23:23:39 +0000 Subject: add tag v1_8_5_91 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_5_91@13046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ruby_1_8_5/ext/openssl/.cvsignore | 5 + ruby_1_8_5/ext/openssl/extconf.rb | 123 +++ ruby_1_8_5/ext/openssl/lib/net/ftptls.rb | 43 + ruby_1_8_5/ext/openssl/lib/net/telnets.rb | 248 +++++ ruby_1_8_5/ext/openssl/lib/openssl.rb | 24 + ruby_1_8_5/ext/openssl/lib/openssl/bn.rb | 35 + ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb | 239 +++++ ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb | 58 ++ ruby_1_8_5/ext/openssl/lib/openssl/digest.rb | 49 + ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb | 135 +++ ruby_1_8_5/ext/openssl/lib/openssl/x509.rb | 154 +++ ruby_1_8_5/ext/openssl/openssl_missing.c | 345 +++++++ ruby_1_8_5/ext/openssl/openssl_missing.h | 130 +++ ruby_1_8_5/ext/openssl/ossl.c | 476 +++++++++ ruby_1_8_5/ext/openssl/ossl.h | 226 +++++ ruby_1_8_5/ext/openssl/ossl_asn1.c | 1166 +++++++++++++++++++++++ ruby_1_8_5/ext/openssl/ossl_asn1.h | 59 ++ ruby_1_8_5/ext/openssl/ossl_bio.c | 73 ++ ruby_1_8_5/ext/openssl/ossl_bio.h | 21 + ruby_1_8_5/ext/openssl/ossl_bn.c | 715 ++++++++++++++ ruby_1_8_5/ext/openssl/ossl_bn.h | 22 + ruby_1_8_5/ext/openssl/ossl_cipher.c | 406 ++++++++ ruby_1_8_5/ext/openssl/ossl_cipher.h | 23 + ruby_1_8_5/ext/openssl/ossl_config.c | 462 +++++++++ ruby_1_8_5/ext/openssl/ossl_config.h | 22 + ruby_1_8_5/ext/openssl/ossl_digest.c | 294 ++++++ ruby_1_8_5/ext/openssl/ossl_digest.h | 23 + ruby_1_8_5/ext/openssl/ossl_engine.c | 393 ++++++++ ruby_1_8_5/ext/openssl/ossl_engine.h | 20 + ruby_1_8_5/ext/openssl/ossl_hmac.c | 220 +++++ ruby_1_8_5/ext/openssl/ossl_hmac.h | 19 + ruby_1_8_5/ext/openssl/ossl_ns_spki.c | 256 +++++ ruby_1_8_5/ext/openssl/ossl_ns_spki.h | 21 + ruby_1_8_5/ext/openssl/ossl_ocsp.c | 769 +++++++++++++++ ruby_1_8_5/ext/openssl/ossl_ocsp.h | 24 + ruby_1_8_5/ext/openssl/ossl_pkcs12.c | 154 +++ ruby_1_8_5/ext/openssl/ossl_pkcs12.h | 16 + ruby_1_8_5/ext/openssl/ossl_pkcs5.h | 6 + ruby_1_8_5/ext/openssl/ossl_pkcs7.c | 993 +++++++++++++++++++ ruby_1_8_5/ext/openssl/ossl_pkcs7.h | 23 + ruby_1_8_5/ext/openssl/ossl_pkey.c | 232 +++++ ruby_1_8_5/ext/openssl/ossl_pkey.h | 120 +++ ruby_1_8_5/ext/openssl/ossl_pkey_dh.c | 458 +++++++++ ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c | 417 ++++++++ ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c | 513 ++++++++++ ruby_1_8_5/ext/openssl/ossl_rand.c | 130 +++ ruby_1_8_5/ext/openssl/ossl_rand.h | 20 + ruby_1_8_5/ext/openssl/ossl_ssl.c | 937 ++++++++++++++++++ ruby_1_8_5/ext/openssl/ossl_ssl.h | 21 + ruby_1_8_5/ext/openssl/ossl_version.h | 16 + ruby_1_8_5/ext/openssl/ossl_x509.c | 104 ++ ruby_1_8_5/ext/openssl/ossl_x509.h | 114 +++ ruby_1_8_5/ext/openssl/ossl_x509attr.c | 249 +++++ ruby_1_8_5/ext/openssl/ossl_x509cert.c | 671 +++++++++++++ ruby_1_8_5/ext/openssl/ossl_x509crl.c | 535 +++++++++++ ruby_1_8_5/ext/openssl/ossl_x509ext.c | 456 +++++++++ ruby_1_8_5/ext/openssl/ossl_x509name.c | 344 +++++++ ruby_1_8_5/ext/openssl/ossl_x509req.c | 466 +++++++++ ruby_1_8_5/ext/openssl/ossl_x509revoked.c | 229 +++++ ruby_1_8_5/ext/openssl/ossl_x509store.c | 613 ++++++++++++ ruby_1_8_5/ext/openssl/ruby_missing.h | 18 + 61 files changed, 15153 insertions(+) create mode 100644 ruby_1_8_5/ext/openssl/.cvsignore create mode 100644 ruby_1_8_5/ext/openssl/extconf.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/net/ftptls.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/net/telnets.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/bn.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/digest.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb create mode 100644 ruby_1_8_5/ext/openssl/lib/openssl/x509.rb create mode 100644 ruby_1_8_5/ext/openssl/openssl_missing.c create mode 100644 ruby_1_8_5/ext/openssl/openssl_missing.h create mode 100644 ruby_1_8_5/ext/openssl/ossl.c create mode 100644 ruby_1_8_5/ext/openssl/ossl.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_asn1.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_asn1.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_bio.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_bio.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_bn.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_bn.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_cipher.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_cipher.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_config.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_config.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_digest.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_digest.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_engine.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_engine.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_hmac.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_hmac.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_ns_spki.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_ns_spki.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_ocsp.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_ocsp.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkcs12.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkcs12.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkcs5.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkcs7.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkcs7.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkey.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkey.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkey_dh.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_rand.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_rand.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_ssl.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_ssl.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_version.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509.h create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509attr.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509cert.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509crl.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509ext.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509name.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509req.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509revoked.c create mode 100644 ruby_1_8_5/ext/openssl/ossl_x509store.c create mode 100644 ruby_1_8_5/ext/openssl/ruby_missing.h (limited to 'ruby_1_8_5/ext/openssl') diff --git a/ruby_1_8_5/ext/openssl/.cvsignore b/ruby_1_8_5/ext/openssl/.cvsignore new file mode 100644 index 0000000000..3a9a9f341f --- /dev/null +++ b/ruby_1_8_5/ext/openssl/.cvsignore @@ -0,0 +1,5 @@ +GNUmakefile +Makefile +mkmf.log +dep +extconf.h diff --git a/ruby_1_8_5/ext/openssl/extconf.rb b/ruby_1_8_5/ext/openssl/extconf.rb new file mode 100644 index 0000000000..b2c5ca5ef8 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/extconf.rb @@ -0,0 +1,123 @@ +=begin += $RCSfile: extconf.rb,v $ -- Generator for Makefile + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: extconf.rb,v 1.21.2.9 2006/06/20 11:18:15 gotoyuzo Exp $ +=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 /gcc/ =~ CONFIG["CC"] + $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("unistd.h") +have_header("sys/time.h") +have_header("assert.h") + +message "=== Checking for required stuff... ===\n" +if $mingw + have_library("wsock32") + have_library("gdi32") +end +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")} +if !result + unless pkg_config("openssl") and have_header("openssl/ssl.h") + 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 + +message "=== Checking for OpenSSL features... ===\n" +have_func("ERR_peek_last_error") +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("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_STORE_get_ex_data") +have_func("X509_STORE_set_ex_data") +have_func("OBJ_NAME_do_all_sorted") +have_func("OPENSSL_cleanse") +if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n") + $defs.push("-DHAVE_VA_ARGS_MACRO") +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") +end +if try_compile(< +#if OPENSSL_VERSION_NUMBER < 0x00907000L +# error "OpenSSL version is less than 0.9.7." +#endif +SRC + 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" diff --git a/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb b/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb new file mode 100644 index 0000000000..43cc136bf6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb @@ -0,0 +1,43 @@ +=begin += $RCSfile: ftptls.rb,v $ -- SSL/TLS enhancement for Net::HTTP. + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2003 Blaz Grilc + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Requirements + += Version + $Id: ftptls.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $ + += Notes + Tested on FreeBSD 5-CURRENT and 4-STABLE + - ruby 1.6.8 (2003-01-17) [i386-freebsd5] + - OpenSSL 0.9.7a Feb 19 2003 + - ruby-openssl-0.2.0.p0 + tested on ftp server: glftpd 1.30 +=end + +require 'socket' +require 'openssl' +require 'net/ftp' + +module Net + class FTPTLS < FTP + def login(user = "anonymous", passwd = nil, acct = nil) + ctx = OpenSSL::SSL::SSLContext.new('SSLv23') + ctx.key = nil + ctx.cert = nil + voidcmd("AUTH TLS") + @sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx) + @sock.connect + super(user, passwd, acct) + voidcmd("PBSZ 0") + end + end +end diff --git a/ruby_1_8_5/ext/openssl/lib/net/telnets.rb b/ruby_1_8_5/ext/openssl/lib/net/telnets.rb new file mode 100644 index 0000000000..d277a5c2a6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/net/telnets.rb @@ -0,0 +1,248 @@ +=begin += $RCSfile: telnets.rb,v $ -- SSL/TLS enhancement for Net::Telnet. + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2001 GOTOU YUUZOU + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: telnets.rb,v 1.1.2.1 2004/12/20 03:49:16 gotoyuzo Exp $ + + 2001/11/06: Contiributed to Ruby/OpenSSL project. + +== class Net::Telnet + +This class will initiate SSL/TLS session automaticaly if the server +sent OPT_STARTTLS. Some options are added for SSL/TLS. + + host = Net::Telnet::new({ + "Host" => "localhost", + "Port" => "telnets", + ## follows are new options. + 'CertFile' => "user.crt", + 'KeyFile' => "user.key", + 'CAFile' => "/some/where/certs/casert.pem", + 'CAPath' => "/some/where/caserts", + 'VerifyMode' => SSL::VERIFY_PEER, + 'VerifyCallback' => verify_proc + }) + +Or, the new options ('Cert', 'Key' and 'CACert') are available from +Michal Rokos's OpenSSL module. + + cert_data = File.open("user.crt"){|io| io.read } + pkey_data = File.open("user.key"){|io| io.read } + cacert_data = File.open("your_ca.pem"){|io| io.read } + host = Net::Telnet::new({ + "Host" => "localhost", + "Port" => "telnets", + 'Cert' => OpenSSL::X509::Certificate.new(cert_data) + 'Key' => OpenSSL::PKey::RSA.new(pkey_data) + 'CACert' => OpenSSL::X509::Certificate.new(cacert_data) + 'CAFile' => "/some/where/certs/casert.pem", + 'CAPath' => "/some/where/caserts", + 'VerifyMode' => SSL::VERIFY_PEER, + 'VerifyCallback' => verify_proc + }) + +This class is expected to be a superset of usual Net::Telnet. +=end + +require "net/telnet" +require "openssl" + +module Net + class Telnet + attr_reader :ssl + + OPT_STARTTLS = 46.chr # "\056" # "\x2e" # Start TLS + TLS_FOLLOWS = 1.chr # "\001" # "\x01" # FOLLOWS (for STARTTLS) + + alias preprocess_orig preprocess + + def ssl?; @ssl; end + + def preprocess(string) + # combine CR+NULL into CR + string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"] + + # combine EOL into "\n" + string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"] + + string.gsub(/#{IAC}( + [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| + [#{DO}#{DONT}#{WILL}#{WONT}][#{OPT_BINARY}-#{OPT_EXOPL}]| + #{SB}[#{OPT_BINARY}-#{OPT_EXOPL}] + (#{IAC}#{IAC}|[^#{IAC}])+#{IAC}#{SE} + )/xno) do + if IAC == $1 # handle escaped IAC characters + IAC + elsif AYT == $1 # respond to "IAC AYT" (are you there) + self.write("nobody here but us pigeons" + EOL) + '' + elsif DO[0] == $1[0] # respond to "IAC DO x" + if OPT_BINARY[0] == $1[1] + @telnet_option["BINARY"] = true + self.write(IAC + WILL + OPT_BINARY) + elsif OPT_STARTTLS[0] == $1[1] + self.write(IAC + WILL + OPT_STARTTLS) + self.write(IAC + SB + OPT_STARTTLS + TLS_FOLLOWS + IAC + SE) + else + self.write(IAC + WONT + $1[1..1]) + end + '' + elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x" + self.write(IAC + WONT + $1[1..1]) + '' + elsif WILL[0] == $1[0] # respond to "IAC WILL x" + if OPT_BINARY[0] == $1[1] + self.write(IAC + DO + OPT_BINARY) + elsif OPT_ECHO[0] == $1[1] + self.write(IAC + DO + OPT_ECHO) + elsif OPT_SGA[0] == $1[1] + @telnet_option["SGA"] = true + self.write(IAC + DO + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) + end + '' + elsif WONT[0] == $1[0] # respond to "IAC WON'T x" + if OPT_ECHO[0] == $1[1] + self.write(IAC + DONT + OPT_ECHO) + elsif OPT_SGA[0] == $1[1] + @telnet_option["SGA"] = false + self.write(IAC + DONT + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) + end + '' + elsif SB[0] == $1[0] # respond to "IAC SB xxx IAC SE" + if OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0] + @sock = OpenSSL::SSL::SSLSocket.new(@sock) + @sock.cert = @options['Cert'] unless @sock.cert + @sock.key = @options['Key'] unless @sock.key + @sock.ca_cert = @options['CACert'] + @sock.ca_file = @options['CAFile'] + @sock.ca_path = @options['CAPath'] + @sock.timeout = @options['Timeout'] + @sock.verify_mode = @options['VerifyMode'] + @sock.verify_callback = @options['VerifyCallback'] + @sock.verify_depth = @options['VerifyDepth'] + @sock.connect + @ssl = true + end + '' + else + '' + end + end + end # preprocess + + alias waitfor_org waitfor + + def waitfor(options) + time_out = @options["Timeout"] + waittime = @options["Waittime"] + + if options.kind_of?(Hash) + prompt = if options.has_key?("Match") + options["Match"] + elsif options.has_key?("Prompt") + options["Prompt"] + elsif options.has_key?("String") + Regexp.new( Regexp.quote(options["String"]) ) + end + time_out = options["Timeout"] if options.has_key?("Timeout") + waittime = options["Waittime"] if options.has_key?("Waittime") + else + prompt = options + end + + if time_out == false + time_out = nil + end + + line = '' + buf = '' + @rest = '' unless @rest + + until(prompt === line and not IO::select([@sock], nil, nil, waittime)) + unless IO::select([@sock], nil, nil, time_out) + raise TimeoutError, "timed-out; wait for the next data" + end + begin + c = @rest + @sock.sysread(1024 * 1024) + @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") + if @options["Telnetmode"] + pos = 0 + catch(:next){ + while true + case c[pos] + when IAC[0] + case c[pos+1] + when DO[0], DONT[0], WILL[0], WONT[0] + throw :next unless c[pos+2] + pos += 3 + when SB[0] + ret = detect_sub_negotiation(c, pos) + throw :next unless ret + pos = ret + when nil + throw :next + else + pos += 2 + end + when nil + throw :next + else + pos += 1 + end + end + } + + buf = preprocess(c[0...pos]) + @rest = c[pos..-1] + end + @log.print(buf) if @options.has_key?("Output_log") + line.concat(buf) + yield buf if block_given? + rescue EOFError # End of file reached + if line == '' + line = nil + yield nil if block_given? + end + break + end + end + line + end + + private + + def detect_sub_negotiation(data, pos) + return nil if data.length < pos+6 # IAC SB x param IAC SE + pos += 3 + while true + case data[pos] + when IAC[0] + if data[pos+1] == SE[0] + pos += 2 + return pos + else + pos += 2 + end + when nil + return nil + else + pos += 1 + end + end + end + + end +end diff --git a/ruby_1_8_5/ext/openssl/lib/openssl.rb b/ruby_1_8_5/ext/openssl/lib/openssl.rb new file mode 100644 index 0000000000..58fd3887e3 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl.rb @@ -0,0 +1,24 @@ +=begin += $RCSfile: openssl.rb,v $ -- Loader for all OpenSSL C-space and Ruby-space definitions + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: openssl.rb,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ +=end + +require 'openssl.so' + +require 'openssl/bn' +require 'openssl/cipher' +require 'openssl/digest' +require 'openssl/ssl' +require 'openssl/x509' + diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb b/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb new file mode 100644 index 0000000000..4a1595c7ab --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb @@ -0,0 +1,35 @@ +=begin += $RCSfile: bn.rb,v $ -- Ruby-space definitions that completes C-space funcs for BN + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: bn.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + class BN + include Comparable + end # BN +end # OpenSSL + +## +# Add double dispatch to Integer +# +class Integer + def to_bn + OpenSSL::BN::new(self) + end +end # Integer + diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb b/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb new file mode 100644 index 0000000000..9eeb19d959 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb @@ -0,0 +1,239 @@ +=begin += $RCSfile: buffering.rb,v $ -- Buffering mix-in module. + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2001 GOTOU YUUZOU + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: buffering.rb,v 1.5.2.4 2005/09/04 22:03:24 gotoyuzo Exp $ +=end + +module Buffering + include Enumerable + attr_accessor :sync + BLOCK_SIZE = 1024*16 + + def initialize(*args) + @eof = false + @rbuffer = "" + @sync = @io.sync + end + + # + # for reading. + # + private + + def fill_rbuff + begin + @rbuffer << self.sysread(BLOCK_SIZE) + rescue Errno::EAGAIN + retry + rescue EOFError + @eof = true + end + end + + 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 + + def read(size=nil, buf=nil) + if size == 0 + if buf + buf.clear + else + buf = "" + end + return @eof ? nil : buf + 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 + + def readpartial(maxlen, buf=nil) + if maxlen == 0 + if buf + buf.clear + else + buf = "" + end + return @eof ? nil : buf + 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 + + def gets(eol=$/) + 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 + consume_rbuff(size) + end + + def each(eol=$/) + while line = self.gets(eol) + yield line + end + end + alias each_line each + + def readlines(eol=$/) + ary = [] + while line = self.gets(eol) + ary << line + end + ary + end + + def readline(eol=$/) + raise EOFError if eof? + gets(eol) + end + + def getc + c = read(1) + c ? c[0] : nil + end + + def each_byte + while c = getc + yield(c) + end + end + + def readchar + raise EOFError if eof? + getc + end + + def ungetc(c) + @rbuffer[0,0] = c.chr + end + + def eof? + fill_rbuff if !@eof && @rbuffer.empty? + @eof && @rbuffer.empty? + end + alias eof eof? + + # + # for writing. + # + private + + 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 + + def write(s) + do_write(s) + s.length + end + + def << (s) + do_write(s) + self + end + + 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 + + def print(*args) + s = "" + args.each{ |arg| s << arg.to_s } + do_write(s) + nil + end + + def printf(s, *args) + do_write(s % args) + nil + end + + def flush + osync = @sync + @sync = true + do_write "" + @sync = osync + end + + def close + flush rescue nil + sysclose + end +end diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb b/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb new file mode 100644 index 0000000000..7825e5e9e6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb @@ -0,0 +1,58 @@ +=begin += $RCSfile: cipher.rb,v $ -- Ruby-space predefined Cipher subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: cipher.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + module 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) + } + + class Cipher + def random_key + str = OpenSSL::Random.random_bytes(self.key_len) + self.key = str + return str + end + + def random_iv + str = OpenSSL::Random.random_bytes(self.iv_len) + self.iv = str + return str + end + end + end # Cipher +end # OpenSSL diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb b/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb new file mode 100644 index 0000000000..6f2c998ff6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb @@ -0,0 +1,49 @@ +=begin += $RCSfile: digest.rb,v $ -- Ruby-space predefined Digest subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: digest.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + module Digest + + alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) + if OPENSSL_VERSION_NUMBER > 0x00908000 + alg += %w(SHA224 SHA256 SHA384 SHA512) + 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 < + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: ssl.rb,v 1.5.2.6 2006/05/23 18:14:05 gotoyuzo Exp $ +=end + +require "openssl" +require "openssl/buffering" +require "fcntl" + +module OpenSSL + module SSL + module SocketForwarder + def addr + to_io.addr + end + + def peeraddr + to_io.peeraddr + end + + def setsockopt(level, optname, optval) + to_io.setsockopt(level, optname, optval) + end + + def getsockopt(level, optname) + to_io.getsockopt(level, optname) + end + + def fcntl(*args) + to_io.fcntl(*args) + end + + def closed? + to_io.closed? + end + + def do_not_reverse_lookup=(flag) + to_io.do_not_reverse_lookup = flag + end + end + + module Nonblock + def initialize(*args) + flag = File::NONBLOCK + flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL) + @io.fcntl(Fcntl::F_SETFL, flag) + super + end + end + + class SSLSocket + include Buffering + include SocketForwarder + include Nonblock + + def post_connection_check(hostname) + check_common_name = true + cert = peer_cert + cert.extensions.each{|ext| + next if ext.oid != "subjectAltName" + ext.value.split(/,\s+/).each{|general_name| + if /\ADNS:(.*)/ =~ general_name + check_common_name = false + reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + elsif /\AIP Address:(.*)/ =~ general_name + check_common_name = false + return true if $1 == hostname + end + } + } + if check_common_name + cert.subject.to_a.each{|oid, value| + if oid == "CN" + reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + end + } + end + raise SSLError, "hostname not match" + end + end + + class SSLServer + include SocketForwarder + attr_accessor :start_immediately + + def initialize(svr, ctx) + @svr = svr + @ctx = ctx + unless ctx.session_id_context + session_id = OpenSSL::Digest::MD5.hexdigest($0) + @ctx.session_id_context = session_id + end + @start_immediately = true + end + + def to_io + @svr + end + + def listen(backlog=5) + @svr.listen(backlog) + end + + def accept + sock = @svr.accept + begin + ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx) + ssl.sync_close = true + ssl.accept if @start_immediately + ssl + rescue SSLError => ex + sock.close + raise ex + end + end + + def close + @svr.close + end + end + end +end diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb b/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb new file mode 100644 index 0000000000..2ad3f8e96e --- /dev/null +++ b/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb @@ -0,0 +1,154 @@ +=begin += $RCSfile: x509.rb,v $ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: x509.rb,v 1.4.2.2 2004/12/19 08:28:33 gotoyuzo Exp $ +=end + +require "openssl" + +module OpenSSL + module X509 + class ExtensionFactory + def create_extension(*arg) + if arg.size > 1 + create_ext(*arg) + else + send("create_ext_from_"+arg[0].class.name.downcase, arg[0]) + end + end + + def create_ext_from_array(ary) + raise ExtensionError, "unexpected array form" if ary.size > 3 + create_ext(ary[0], ary[1], ary[2]) + end + + def create_ext_from_string(str) # "oid = critical, value" + oid, value = str.split(/=/, 2) + oid.strip! + value.strip! + create_ext(oid, value) + end + + def create_ext_from_hash(hash) + create_ext(hash["oid"], hash["value"], hash["critical"]) + end + end + + class Extension + def to_s # "oid = critical, value" + str = self.oid + str << " = " + str << "critical, " if self.critical? + str << self.value.gsub(/\n/, ", ") + end + + def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} + {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?} + end + + def to_a + [ self.oid, self.value, self.critical? ] + end + end + + class Name + module RFC2253DN + Special = ',=+<>#;' + HexChar = /[0-9a-fA-F]/ + HexPair = /#{HexChar}#{HexChar}/ + HexString = /#{HexPair}+/ + Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/ + StringChar = /[^#{Special}\\"]/ + QuoteChar = /[^\\"]/ + AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/ + AttributeValue = / + (?!["#])((?:#{StringChar}|#{Pair})*)| + \#(#{HexString})| + "((?:#{QuoteChar}|#{Pair})*)" + /x + TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/ + + module_function + + def expand_pair(str) + return nil unless str + return str.gsub(Pair){|pair| + case pair.size + when 2 then pair[1,1] + when 3 then Integer("0x#{pair[1,2]}").chr + else raise OpenSSL::X509::NameError, "invalid pair: #{str}" + end + } + end + + def expand_hexstring(str) + return nil unless str + der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr } + a1 = OpenSSL::ASN1.decode(der) + return a1.value, a1.tag + end + + def expand_value(str1, str2, str3) + value = expand_pair(str1) + value, tag = expand_hexstring(str2) unless value + value = expand_pair(str3) unless value + return value, tag + end + + def scan(dn) + str = dn + ary = [] + while true + if md = TypeAndValue.match(str) + matched = md.to_s + remain = md.post_match + type = md[1] + value, tag = expand_value(md[2], md[3], md[4]) rescue nil + if value + type_and_value = [type, value] + type_and_value.push(tag) if tag + ary.unshift(type_and_value) + if remain.length > 2 && remain[0] == ?, + str = remain[1..-1] + next + elsif remain.length > 2 && remain[0] == ?+ + raise OpenSSL::X509::NameError, + "multi-valued RDN is not supported: #{dn}" + elsif remain.empty? + break + end + end + end + msg_dn = dn[0, dn.length - str.length] + " =>" + str + raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}" + end + return ary + end + end + + class <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)) + return 0; + return 1; +} +#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); +} + +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; icrl->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 + diff --git a/ruby_1_8_5/ext/openssl/openssl_missing.h b/ruby_1_8_5/ext/openssl/openssl_missing.h new file mode 100644 index 0000000000..8d580f5ee8 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/openssl_missing.h @@ -0,0 +1,130 @@ +/* + * $Id: openssl_missing.h,v 1.2.2.2 2005/04/15 19:16:18 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * 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 + +/* + * 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( \ + (char *(*)())d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,bp,(char **)x,cb,u) +#endif + +#if !defined(PEM_write_bio_DSAPublicKey) +# define PEM_write_bio_DSAPublicKey(bp,x) \ + PEM_ASN1_write_bio((int (*)())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((int (*)())i2d_DSAPrivateKey, \ + (char *(*)())d2i_DSAPrivateKey,(char *)dsa) +#endif + +#if !defined(DSAPublicKey_dup) +# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((int (*)())i2d_DSAPublicKey, \ + (char *(*)())d2i_DSAPublicKey,(char *)dsa) +#endif + +#if !defined(X509_REVOKED_dup) +# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((int (*)())i2d_X509_REVOKED, \ + (char *(*)())d2i_X509_REVOKED, (char *)rev) +#endif + +#if !defined(PKCS7_SIGNER_INFO_dup) +# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((int (*)())i2d_PKCS7_SIGNER_INFO, \ + (char *(*)())d2i_PKCS7_SIGNER_INFO, (char *)si) +#endif + +#if !defined(PKCS7_RECIP_INFO_dup) +# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((int (*)())i2d_PKCS7_RECIP_INFO, \ + (char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri) +#endif + +void HMAC_CTX_init(HMAC_CTX *ctx); +int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); +void HMAC_CTX_cleanup(HMAC_CTX *ctx); + +EVP_MD_CTX *EVP_MD_CTX_create(void); +void EVP_MD_CTX_init(EVP_MD_CTX *ctx); +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + +#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 + +void *X509_STORE_get_ex_data(X509_STORE *str, int idx); +int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data); +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_sort(X509_CRL *c); +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_rand_range(BIGNUM *r, BIGNUM *range); +int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range); +char *CONF_get1_default_config_file(void); +int PEM_def_callback(char *buf, int num, int w, void *key); + +#if defined(__cplusplus) +} +#endif + + +#endif /* _OSSL_OPENSSL_MISSING_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl.c b/ruby_1_8_5/ext/openssl/ossl.c new file mode 100644 index 0000000000..01c5ca2a04 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl.c @@ -0,0 +1,476 @@ +/* + * $Id: ossl.c,v 1.11.2.6 2005/11/01 01:52:13 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" +#include /* for ossl_raise */ + +/* + * String to HEXString conversion + */ +int +string2hex(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 + */ +STACK_OF(X509) * +ossl_x509_ary2sk0(VALUE ary) +{ + STACK_OF(X509) *sk; + VALUE val; + X509 *x509; + int i; + + Check_Type(ary, T_ARRAY); + sk = sk_X509_new_null(); + if (!sk) ossl_raise(eOSSLError, NULL); + + for (i = 0; i < RARRAY(ary)->len; i++) { + val = rb_ary_entry(ary, i); + if (!rb_obj_is_kind_of(val, cX509Cert)) { + sk_X509_pop_free(sk, X509_free); + ossl_raise(eOSSLError, "object not X509 cert in array"); + } + x509 = DupX509CertPtr(val); /* NEED TO DUP */ + sk_X509_push(sk, x509); + } + return sk; +} + +STACK_OF(X509) * +ossl_protect_x509_ary2sk(VALUE ary, int *status) +{ + return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0, + ary, status); +} + +STACK_OF(X509) * +ossl_x509_ary2sk(VALUE ary) +{ + STACK_OF(X509) *sk; + int status = 0; + + sk = ossl_protect_x509_ary2sk(ary, &status); + if(status) rb_jump_tag(status); + + return sk; +} + +#define OSSL_IMPL_SK2ARY(name, type) \ +VALUE \ +ossl_##name##_sk2ary(STACK *sk) \ +{ \ + type *t; \ + int i, num; \ + VALUE ary; \ + \ + if (!sk) { \ + OSSL_Debug("empty sk!"); \ + return Qnil; \ + } \ + num = sk_num(sk); \ + if (num < 0) { \ + OSSL_Debug("items in sk < -1???"); \ + return rb_ary_new(); \ + } \ + ary = rb_ary_new2(num); \ + \ + for (i=0; iptr, 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(pass)->len; + 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(pass)->ptr, 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_ensure(ossl_call_verify_cb_proc, (VALUE)&args, + ossl_x509stctx_clear_ptr, rctx); + } + 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 + */ +void +ossl_raise(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) { + va_start(args, fmt); + len = vsnprintf(buf, BUFSIZ, fmt, args); + va_end(args); + } + if (len < BUFSIZ && e) { + if (dOSSL == Qtrue) /* FULL INFO */ + msg = ERR_error_string(e, NULL); + else + msg = ERR_reason_error_string(e); + fmt = len ? ": %s" : "%s"; + len += snprintf(buf+len, BUFSIZ-len, fmt, 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 = strlen(buf); + rb_exc_raise(rb_exc_new(exc, buf, len)); +} + +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 + +static VALUE +ossl_debug_get(VALUE self) +{ + return dOSSL; +} + +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; +} + +/* + * OSSL library init + */ +void +Init_openssl() +{ + /* + * Init timezone info + */ +#if 0 + tzset(); +#endif + + /* + * Init all digests, ciphers + */ + /* CRYPTO_malloc_init(); */ + /* ENGINE_load_builtin_engines(); */ + OpenSSL_add_ssl_algorithms(); + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + + /* + * FIXME: + * On unload do: + */ +#if 0 + CONF_modules_unload(1); + destroy_ui_method(); + EVP_cleanup(); + ENGINE_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_state(0); + ERR_free_strings(); +#endif + + /* + * Init main module + */ + mOSSL = rb_define_module("OpenSSL"); + + /* + * Constants + */ + rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); + rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); + rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); + + /* + * Generic error, + * common for all classes under OpenSSL module + */ + eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); + + /* + * Verify callback Proc index for ext-data + */ + ossl_verify_cb_idx = + X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0); + + /* + * Init debug core + */ + dOSSL = Qfalse; + rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); + rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); + rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); + + /* + * Get ID of to_der + */ + ossl_s_to_der = rb_intern("to_der"); + + /* + * Init components + */ + Init_ossl_bn(); + Init_ossl_cipher(); + Init_ossl_config(); + Init_ossl_digest(); + Init_ossl_hmac(); + Init_ossl_ns_spki(); + Init_ossl_pkcs12(); + Init_ossl_pkcs7(); + Init_ossl_pkey(); + Init_ossl_rand(); + Init_ossl_ssl(); + Init_ossl_x509(); + Init_ossl_ocsp(); + Init_ossl_engine(); + Init_ossl_asn1(); +} + +#if defined(OSSL_DEBUG) +/* + * Check if all symbols are OK with 'make LDSHARED=gcc all' + */ +int +main(int argc, char *argv[], char *env[]) +{ + return 0; +} +#endif /* OSSL_DEBUG */ + diff --git a/ruby_1_8_5/ext/openssl/ossl.h b/ruby_1_8_5/ext/openssl/ossl.h new file mode 100644 index 0000000000..336b468eb2 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl.h @@ -0,0 +1,226 @@ +/* + * $Id: ossl.h,v 1.14.2.4.2.1 2006/12/25 11:16:49 shyouhei Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_H_) +#define _OSSL_H_ + +#include RUBY_EXTCONF_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + *_FILE_OFFSET_BITS needs to be defined before some system headers on + * Solaris. + */ +#include "config.h" + +/* + * Check the OpenSSL version + * The only supported are: + * OpenSSL >= 0.9.7 + */ +#include + +#ifdef HAVE_ASSERT_H +# include +#else +# define assert(condition) +#endif + +#if defined(_WIN32) +# define OpenFile WINAPI_OpenFile +# define OSSL_NO_CONF_API 1 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef X509_NAME +#undef PKCS7_SIGNER_INFO +#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE) +# define OSSL_ENGINE_ENABLED +# include +#endif +#if defined(HAVE_OPENSSL_OCSP_H) +# define OSSL_OCSP_ENABLED +# include +#endif +#if defined(_WIN32) +# undef OpenFile +#endif + +/* + * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it! + */ +#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/ +# undef RFILE +#endif +#include +#include + +/* + * Common Module + */ +extern VALUE mOSSL; + +/* + * Common Error Class + */ +extern VALUE eOSSLError; + +/* + * CheckTypes + */ +#define OSSL_Check_Kind(obj, klass) do {\ + if (!rb_obj_is_kind_of(obj, klass)) {\ + ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\ + rb_obj_classname(obj), rb_class2name(klass));\ + }\ +} while (0) + +#define OSSL_Check_Instance(obj, klass) do {\ + if (!rb_obj_is_instance_of(obj, klass)) {\ + ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\ + rb_obj_classname(obj), rb_class2name(klass));\ + }\ +} while (0) + +#define OSSL_Check_Same_Class(obj1, obj2) do {\ + if (!rb_obj_is_instance_of(obj1, rb_obj_class(obj2))) {\ + ossl_raise(rb_eTypeError, "wrong argument type");\ + }\ +} while (0) + +/* + * String to HEXString conversion + */ +int string2hex(char *, int, char **, int *); + +/* + * Data Conversion + */ +STACK_OF(X509) *ossl_x509_ary2sk0(VALUE); +STACK_OF(X509) *ossl_x509_ary2sk(VALUE); +STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); +VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs); +VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl); +VALUE ossl_buf2str(char *buf, int len); +#define ossl_str_adjust(str, p) \ +do{\ + int len = RSTRING(str)->len;\ + int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\ + assert(newlen <= len);\ + RSTRING(str)->len = newlen;\ + RSTRING(str)->ptr[newlen] = 0;\ +}while(0) + +/* + * our default PEM callback + */ +int ossl_pem_passwd_cb(char *, int, int, void *); + +/* + * ERRor messages + */ +#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error()) +NORETURN(void ossl_raise(VALUE, const char *, ...)); + +/* + * Verify callback + */ +extern int ossl_verify_cb_idx; + +struct ossl_verify_cb_args { + VALUE proc; + VALUE preverify_ok; + VALUE store_ctx; +}; + +VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *); +int ossl_verify_cb(int, X509_STORE_CTX *); + +/* + * String to DER String + */ +extern ID ossl_s_to_der; +VALUE ossl_to_der(VALUE); +VALUE ossl_to_der_if_possible(VALUE); + +/* + * Debug + */ +extern VALUE dOSSL; + +#if defined(HAVE_VA_ARGS_MACRO) +#define OSSL_Debug(fmt, ...) do { \ + if (dOSSL == Qtrue) { \ + fprintf(stderr, "OSSL_DEBUG: "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \ + } \ +} while (0) + +#define OSSL_Warning(fmt, ...) do { \ + OSSL_Debug(fmt, ##__VA_ARGS__); \ + rb_warning(fmt, ##__VA_ARGS__); \ +} while (0) + +#define OSSL_Warn(fmt, ...) do { \ + OSSL_Debug(fmt, ##__VA_ARGS__); \ + rb_warn(fmt, ##__VA_ARGS__); \ +} while (0) +#else +void ossl_debug(const char *, ...); +#define OSSL_Debug ossl_debug +#define OSSL_Warning rb_warning +#define OSSL_Warn rb_warn +#endif + +/* + * Include all parts + */ +#include "openssl_missing.h" +#include "ruby_missing.h" +#include "ossl_asn1.h" +#include "ossl_bio.h" +#include "ossl_bn.h" +#include "ossl_cipher.h" +#include "ossl_config.h" +#include "ossl_digest.h" +#include "ossl_hmac.h" +#include "ossl_ns_spki.h" +#include "ossl_ocsp.h" +#include "ossl_pkcs12.h" +#include "ossl_pkcs7.h" +#include "ossl_pkcs5.h" +#include "ossl_pkey.h" +#include "ossl_rand.h" +#include "ossl_ssl.h" +#include "ossl_version.h" +#include "ossl_x509.h" +#include "ossl_engine.h" + +void Init_openssl(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* _OSSL_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_asn1.c b/ruby_1_8_5/ext/openssl/ossl_asn1.c new file mode 100644 index 0000000000..6bc5b88e8f --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_asn1.c @@ -0,0 +1,1166 @@ +/* + * $Id: ossl_asn1.c,v 1.5.2.9 2006/04/29 13:52:15 gotoyuzo Exp $ + * 'OpenSSL for Ruby' team members + * Copyright (C) 2003 + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#if defined(HAVE_SYS_TIME_H) +# include +#elif !defined(NT) && !defined(_WIN32) +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif + +/* + * DATE conversion + */ +VALUE +asn1time_to_time(ASN1_TIME *time) +{ + struct tm tm; + VALUE argv[6]; + + if (!time || !time->data) return Qnil; + memset(&tm, 0, sizeof(struct tm)); + + switch (time->type) { + case V_ASN1_UTCTIME: + if (sscanf(time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + ossl_raise(rb_eTypeError, "bad UTCTIME format"); + } + if (tm.tm_year < 69) { + tm.tm_year += 2000; + } else { + tm.tm_year += 1900; + } + break; + case V_ASN1_GENERALIZEDTIME: + if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" ); + } + break; + default: + rb_warning("unknown time format"); + return Qnil; + } + argv[0] = INT2NUM(tm.tm_year); + argv[1] = INT2NUM(tm.tm_mon); + argv[2] = INT2NUM(tm.tm_mday); + argv[3] = INT2NUM(tm.tm_hour); + argv[4] = INT2NUM(tm.tm_min); + argv[5] = INT2NUM(tm.tm_sec); + + return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); +} + +/* + * This function is not exported in Ruby's *.h + */ +extern struct timeval rb_time_timeval(VALUE); + +time_t +time_to_time_t(VALUE time) +{ + return (time_t)NUM2LONG(rb_Integer(time)); +} + +/* + * STRING conversion + */ +VALUE +asn1str_to_str(ASN1_STRING *str) +{ + return rb_str_new(str->data, str->length); +} + +/* + * ASN1_INTEGER conversions + * TODO: Make a decision what's the right way to do this. + */ +#define DO_IT_VIA_RUBY 0 +VALUE +asn1integer_to_num(ASN1_INTEGER *ai) +{ + BIGNUM *bn; +#if DO_IT_VIA_RUBY + char *txt; +#endif + VALUE num; + + if (!ai) { + ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!"); + } + if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) { + ossl_raise(eOSSLError, NULL); + } +#if DO_IT_VIA_RUBY + if (!(txt = BN_bn2dec(bn))) { + BN_free(bn); + ossl_raise(eOSSLError, NULL); + } + num = rb_cstr_to_inum(txt, 10, Qtrue); + OPENSSL_free(txt); +#else + num = ossl_bn_new(bn); +#endif + BN_free(bn); + + return num; +} + +#if DO_IT_VIA_RUBY +ASN1_INTEGER * +num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) +{ + BIGNUM *bn = NULL; + + if (RTEST(rb_obj_is_kind_of(obj, cBN))) { + bn = GetBNPtr(obj); + } else { + obj = rb_String(obj); + if (!BN_dec2bn(&bn, StringValuePtr(obj))) { + ossl_raise(eOSSLError, NULL); + } + } + if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) { + BN_free(bn); + ossl_raise(eOSSLError, NULL); + } + BN_free(bn); + return ai; +} +#else +ASN1_INTEGER * +num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) +{ + BIGNUM *bn = GetBNPtr(obj); + + if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) { + ossl_raise(eOSSLError, NULL); + } + return ai; +} +#endif + +/********/ +/* + * ASN1 module + */ +#define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value")) +#define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag")) +#define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging")) +#define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class")) + +#define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v)) +#define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v)) +#define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v)) +#define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v)) + +VALUE mASN1; +VALUE eASN1Error; + +VALUE cASN1Data; +VALUE cASN1Primitive; +VALUE cASN1Constructive; + +VALUE cASN1Boolean; /* BOOLEAN */ +VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ +VALUE cASN1BitString; /* BIT STRING */ +VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ +VALUE cASN1NumericString, cASN1PrintableString; +VALUE cASN1T61String, cASN1VideotexString; +VALUE cASN1IA5String, cASN1GraphicString; +VALUE cASN1ISO64String, cASN1GeneralString; +VALUE cASN1UniversalString, cASN1BMPString; +VALUE cASN1Null; /* NULL */ +VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ +VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ +VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ + +static ID sIMPLICIT, sEXPLICIT; +static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE; + +/* + * Ruby to ASN1 converters + */ +static ASN1_BOOLEAN +obj_to_asn1bool(VALUE obj) +{ + return RTEST(obj) ? 0xff : 0x100; +} + +static ASN1_INTEGER* +obj_to_asn1int(VALUE obj) +{ + return num_to_asn1integer(obj, NULL); +} + +static ASN1_BIT_STRING* +obj_to_asn1bstr(VALUE obj, long unused_bits) +{ + ASN1_BIT_STRING *bstr; + + if(unused_bits < 0) unused_bits = 0; + StringValue(obj); + if(!(bstr = ASN1_BIT_STRING_new())) + ossl_raise(eASN1Error, NULL); + ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len); + bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ + bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07); + + return bstr; +} + +static ASN1_STRING* +obj_to_asn1str(VALUE obj) +{ + ASN1_STRING *str; + + StringValue(obj); + if(!(str = ASN1_STRING_new())) + ossl_raise(eASN1Error, NULL); + ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len); + + return str; +} + +static ASN1_NULL* +obj_to_asn1null(VALUE obj) +{ + ASN1_NULL *null; + + if(!NIL_P(obj)) + ossl_raise(eASN1Error, "nil expected"); + if(!(null = ASN1_NULL_new())) + ossl_raise(eASN1Error, NULL); + + return null; +} + +static ASN1_OBJECT* +obj_to_asn1obj(VALUE obj) +{ + ASN1_OBJECT *a1obj; + + StringValue(obj); + a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0); + if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1); + if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID"); + + return a1obj; +} + +static ASN1_UTCTIME* +obj_to_asn1utime(VALUE time) +{ + time_t sec; + ASN1_UTCTIME *t; + + sec = time_to_time_t(time); + if(!(t = ASN1_UTCTIME_set(NULL, sec))) + ossl_raise(eASN1Error, NULL); + + return t; +} + +static ASN1_GENERALIZEDTIME* +obj_to_asn1gtime(VALUE time) +{ + time_t sec; + ASN1_GENERALIZEDTIME *t; + + sec = time_to_time_t(time); + if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec))) + ossl_raise(eASN1Error, NULL); + + return t; +} + +static ASN1_STRING* +obj_to_asn1derstr(VALUE obj) +{ + ASN1_STRING *a1str; + VALUE str; + + str = ossl_to_der(obj); + if(!(a1str = ASN1_STRING_new())) + ossl_raise(eASN1Error, NULL); + ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len); + + return a1str; +} + +/* + * DER to Ruby converters + */ +static VALUE +decode_bool(unsigned char* der, int length) +{ + int bool; + unsigned char *p; + + p = der; + if((bool = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0) + ossl_raise(eASN1Error, NULL); + + return bool ? Qtrue : Qfalse; +} + +static VALUE +decode_int(unsigned char* der, int length) +{ + ASN1_INTEGER *ai; + unsigned char *p; + VALUE ret; + int status = 0; + + p = der; + if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num, + (VALUE)ai, &status); + ASN1_INTEGER_free(ai); + if(status) rb_jump_tag(status); + + return ret; +} + +static VALUE +decode_bstr(unsigned char* der, int length, long *unused_bits) +{ + ASN1_BIT_STRING *bstr; + unsigned char *p, *buf; + long len; + VALUE ret; + + p = der; + if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + len = bstr->length; + if(!(buf = OPENSSL_malloc(len))){ + ASN1_BIT_STRING_free(bstr); + ossl_raise(eASN1Error, NULL); + } + *unused_bits = 0; + if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT) + *unused_bits = bstr->flags & 0x07; + memcpy(buf, bstr->data, len); + ASN1_BIT_STRING_free(bstr); + ret = ossl_buf2str(buf, len); + + return ret; +} + +static VALUE +decode_enum(unsigned char* der, int length) +{ + ASN1_ENUMERATED *ai; + unsigned char *p; + VALUE ret; + int status = 0; + + p = der; + if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num, + (VALUE)ai, &status); + ASN1_ENUMERATED_free(ai); + if(status) rb_jump_tag(status); + + return ret; +} + +static VALUE +decode_null(unsigned char* der, int length) +{ + ASN1_NULL *null; + unsigned char *p; + + p = der; + if(!(null = d2i_ASN1_NULL(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + ASN1_NULL_free(null); + + return Qnil; +} + +static VALUE +decode_obj(unsigned char* der, int length) +{ + ASN1_OBJECT *obj; + unsigned char *p; + VALUE ret; + int nid; + BIO *bio; + + p = der; + if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + if((nid = OBJ_obj2nid(obj)) != NID_undef){ + ASN1_OBJECT_free(obj); + ret = rb_str_new2(OBJ_nid2sn(nid)); + } + else{ + if(!(bio = BIO_new(BIO_s_mem()))){ + ASN1_OBJECT_free(obj); + ossl_raise(eASN1Error, NULL); + } + i2a_ASN1_OBJECT(bio, obj); + ASN1_OBJECT_free(obj); + ret = ossl_membio2str(bio); + } + + return ret; +} + +static VALUE +decode_time(unsigned char* der, int length) +{ + ASN1_TIME *time; + unsigned char *p; + VALUE ret; + int status = 0; + + p = der; + if(!(time = d2i_ASN1_TIME(NULL, &p, length))) + ossl_raise(eASN1Error, NULL); + ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time, + (VALUE)time, &status); + ASN1_TIME_free(time); + if(status) rb_jump_tag(status); + + return ret; +} + +/********/ + +typedef struct { + char *name; + VALUE *klass; +} ossl_asn1_info_t; + +static ossl_asn1_info_t ossl_asn1_info[] = { + { "EOC", NULL, }, /* 0 */ + { "BOOLEAN", &cASN1Boolean, }, /* 1 */ + { "INTEGER", &cASN1Integer, }, /* 2 */ + { "BIT_STRING", &cASN1BitString, }, /* 3 */ + { "OCTET_STRING", &cASN1OctetString, }, /* 4 */ + { "NULL", &cASN1Null, }, /* 5 */ + { "OBJECT", &cASN1ObjectId, }, /* 6 */ + { "OBJECT_DESCRIPTOR", NULL, }, /* 7 */ + { "EXTERNAL", NULL, }, /* 8 */ + { "REAL", NULL, }, /* 9 */ + { "ENUMERATED", &cASN1Enumerated, }, /* 10 */ + { "EMBEDDED_PDV", NULL, }, /* 11 */ + { "UTF8STRING", &cASN1UTF8String, }, /* 12 */ + { "RELATIVE_OID", NULL, }, /* 13 */ + { "[UNIVERSAL 14]", NULL, }, /* 14 */ + { "[UNIVERSAL 15]", NULL, }, /* 15 */ + { "SEQUENCE", &cASN1Sequence, }, /* 16 */ + { "SET", &cASN1Set, }, /* 17 */ + { "NUMERICSTRING", &cASN1NumericString, }, /* 18 */ + { "PRINTABLESTRING", &cASN1PrintableString, }, /* 19 */ + { "T61STRING", &cASN1T61String, }, /* 20 */ + { "VIDEOTEXSTRING", &cASN1VideotexString, }, /* 21 */ + { "IA5STRING", &cASN1IA5String, }, /* 22 */ + { "UTCTIME", &cASN1UTCTime, }, /* 23 */ + { "GENERALIZEDTIME", &cASN1GeneralizedTime, }, /* 24 */ + { "GRAPHICSTRING", &cASN1GraphicString, }, /* 25 */ + { "ISO64STRING", &cASN1ISO64String, }, /* 26 */ + { "GENERALSTRING", &cASN1GeneralString, }, /* 27 */ + { "UNIVERSALSTRING", &cASN1UniversalString, }, /* 28 */ + { "CHARACTER_STRING", NULL, }, /* 29 */ + { "BMPSTRING", &cASN1BMPString, }, /* 30 */ +}; + +int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0])); + +static int ossl_asn1_default_tag(VALUE obj); + +ASN1_TYPE* +ossl_asn1_get_asn1type(VALUE obj) +{ + ASN1_TYPE *ret; + VALUE value, rflag; + void *ptr; + void (*free_func)(); + long tag, flag; + + tag = ossl_asn1_default_tag(obj); + value = ossl_asn1_get_value(obj); + switch(tag){ + case V_ASN1_BOOLEAN: + ptr = (void*)obj_to_asn1bool(value); + free_func = NULL; + break; + case V_ASN1_INTEGER: /* FALLTHROUGH */ + case V_ASN1_ENUMERATED: + ptr = obj_to_asn1int(value); + free_func = ASN1_INTEGER_free; + break; + case V_ASN1_BIT_STRING: + rflag = rb_attr_get(obj, rb_intern("@unused_bits")); + flag = NIL_P(rflag) ? -1 : NUM2INT(rflag); + ptr = obj_to_asn1bstr(value, flag); + free_func = ASN1_BIT_STRING_free; + break; + case V_ASN1_NULL: + ptr = obj_to_asn1null(value); + free_func = ASN1_NULL_free; + break; + case V_ASN1_OCTET_STRING: /* FALLTHROUGH */ + case V_ASN1_UTF8STRING: /* FALLTHROUGH */ + case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */ + case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */ + case V_ASN1_T61STRING: /* FALLTHROUGH */ + case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */ + case V_ASN1_IA5STRING: /* FALLTHROUGH */ + case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */ + case V_ASN1_ISO64STRING: /* FALLTHROUGH */ + case V_ASN1_GENERALSTRING: /* FALLTHROUGH */ + case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */ + case V_ASN1_BMPSTRING: + ptr = obj_to_asn1str(value); + free_func = ASN1_STRING_free; + break; + case V_ASN1_OBJECT: + ptr = obj_to_asn1obj(value); + free_func = ASN1_OBJECT_free; + break; + case V_ASN1_UTCTIME: + ptr = obj_to_asn1utime(value); + free_func = ASN1_TIME_free; + break; + case V_ASN1_GENERALIZEDTIME: + ptr = obj_to_asn1gtime(value); + free_func = ASN1_TIME_free; + break; + case V_ASN1_SET: /* FALLTHROUGH */ + case V_ASN1_SEQUENCE: + ptr = obj_to_asn1derstr(obj); + free_func = ASN1_STRING_free; + break; + default: + ossl_raise(eASN1Error, "unsupported ASN.1 type"); + } + if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){ + if(free_func) free_func(ptr); + ossl_raise(eASN1Error, "ASN1_TYPE alloc failure"); + } + memset(ret, 0, sizeof(ASN1_TYPE)); + ASN1_TYPE_set(ret, tag, ptr); + + return ret; +} + +static int +ossl_asn1_default_tag(VALUE obj) +{ + int i; + + for(i = 0; i < ossl_asn1_info_size; i++){ + if(ossl_asn1_info[i].klass && + rb_obj_is_kind_of(obj, *ossl_asn1_info[i].klass)){ + return i; + } + } + ossl_raise(eASN1Error, "universal tag for %s not found", + rb_class2name(CLASS_OF(obj))); + + return -1; /* dummy */ +} + +static int +ossl_asn1_tag(VALUE obj) +{ + VALUE tag; + + tag = ossl_asn1_get_tag(obj); + if(NIL_P(tag)) + ossl_raise(eASN1Error, "tag number not specified"); + + return NUM2INT(tag); +} + +static int +ossl_asn1_is_explicit(VALUE obj) +{ + VALUE s; + int ret = -1; + + s = ossl_asn1_get_tagging(obj); + if(NIL_P(s)) return 0; + else if(SYMBOL_P(s)){ + if (SYM2ID(s) == sIMPLICIT) + ret = 0; + else if (SYM2ID(s) == sEXPLICIT) + ret = 1; + } + if(ret < 0){ + ossl_raise(eASN1Error, "invalid tag default"); + } + + return ret; +} + +static int +ossl_asn1_tag_class(VALUE obj) +{ + VALUE s; + int ret = -1; + + s = ossl_asn1_get_tag_class(obj); + if(NIL_P(s)) ret = V_ASN1_UNIVERSAL; + else if(SYMBOL_P(s)){ + if (SYM2ID(s) == sUNIVERSAL) + ret = V_ASN1_UNIVERSAL; + else if (SYM2ID(s) == sAPPLICATION) + ret = V_ASN1_APPLICATION; + else if (SYM2ID(s) == sCONTEXT_SPECIFIC) + ret = V_ASN1_CONTEXT_SPECIFIC; + else if (SYM2ID(s) == sPRIVATE) + ret = V_ASN1_PRIVATE; + } + if(ret < 0){ + ossl_raise(eASN1Error, "invalid tag class"); + } + + return ret; +} + +static VALUE +ossl_asn1_class2sym(int tc) +{ + if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) + return ID2SYM(sPRIVATE); + else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) + return ID2SYM(sCONTEXT_SPECIFIC); + else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) + return ID2SYM(sAPPLICATION); + else + return ID2SYM(sUNIVERSAL); +} + +static VALUE +ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class) +{ + if(!SYMBOL_P(tag_class)) + ossl_raise(eASN1Error, "invalid tag class"); + if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31) + ossl_raise(eASN1Error, "tag number for Universal too large"); + ossl_asn1_set_tag(self, tag); + ossl_asn1_set_value(self, value); + ossl_asn1_set_tag_class(self, tag_class); + + return self; +} + +static VALUE +join_der_i(VALUE i, VALUE str) +{ + i = ossl_to_der_if_possible(i); + StringValue(i); + rb_str_append(str, i); + return Qnil; +} + +static VALUE +join_der(VALUE enumerable) +{ + VALUE str = rb_str_new(0, 0); + rb_iterate(rb_each, enumerable, join_der_i, str); + return str; +} + +static VALUE +ossl_asn1data_to_der(VALUE self) +{ + VALUE value, der; + int tag, tag_class, is_cons = 0; + long length; + unsigned char *p; + + value = ossl_asn1_get_value(self); + if(rb_obj_is_kind_of(value, rb_cArray)){ + is_cons = 1; + value = join_der(value); + } + StringValue(value); + + tag = ossl_asn1_tag(self); + tag_class = ossl_asn1_tag_class(self); + if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0) + ossl_raise(eASN1Error, NULL); + der = rb_str_new(0, length); + p = RSTRING(der)->ptr; + ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class); + memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len); + p += RSTRING(value)->len; + ossl_str_adjust(der, p); + + return der; +} + +static VALUE +ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth, + int once, int yield) +{ + unsigned char *start, *p; + long len, off = *offset; + int hlen, tag, tc, j; + VALUE ary, asn1data, value, tag_class; + + ary = rb_ary_new(); + p = *pp; + while(length > 0){ + start = p; + j = ASN1_get_object(&p, &len, &tag, &tc, length); + if(j & 0x80) ossl_raise(eASN1Error, NULL); + hlen = p - start; + if(yield){ + VALUE arg = rb_ary_new(); + rb_ary_push(arg, LONG2NUM(depth)); + rb_ary_push(arg, LONG2NUM(off)); + rb_ary_push(arg, LONG2NUM(hlen)); + rb_ary_push(arg, LONG2NUM(len)); + rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse); + rb_ary_push(arg, ossl_asn1_class2sym(tc)); + rb_ary_push(arg, INT2NUM(tag)); + rb_yield(arg); + } + length -= hlen; + off += hlen; + if(len > length) ossl_raise(eASN1Error, "value is too short"); + if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) + tag_class = sPRIVATE; + else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) + tag_class = sCONTEXT_SPECIFIC; + else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) + tag_class = sAPPLICATION; + else + tag_class = sUNIVERSAL; + if(j & V_ASN1_CONSTRUCTED){ + /* TODO: if j == 0x21 it is indefinite length object. */ + if((j == 0x21) && (len == 0)){ + long lastoff = off; + value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield); + len = off - lastoff; + } + else value = ossl_asn1_decode0(&p, len, &off, depth+1, 0, yield); + } + else{ + value = rb_str_new(p, len); + p += len; + off += len; + } + if(tag_class == sUNIVERSAL && + tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){ + VALUE klass = *ossl_asn1_info[tag].klass; + long flag = 0; + if(!rb_obj_is_kind_of(value, rb_cArray)){ + switch(tag){ + case V_ASN1_BOOLEAN: + value = decode_bool(start, hlen+len); + break; + case V_ASN1_INTEGER: + value = decode_int(start, hlen+len); + break; + case V_ASN1_BIT_STRING: + value = decode_bstr(start, hlen+len, &flag); + break; + case V_ASN1_NULL: + value = decode_null(start, hlen+len); + break; + case V_ASN1_ENUMERATED: + value = decode_enum(start, hlen+len); + break; + case V_ASN1_OBJECT: + value = decode_obj(start, hlen+len); + break; + case V_ASN1_UTCTIME: /* FALLTHROUGH */ + case V_ASN1_GENERALIZEDTIME: + value = decode_time(start, hlen+len); + break; + default: + /* use original value */ + break; + } + } + asn1data = rb_funcall(klass, rb_intern("new"), 1, value); + if(tag == V_ASN1_BIT_STRING){ + rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag)); + } + } + else{ + asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3, + value, INT2NUM(tag), ID2SYM(tag_class)); + } + rb_ary_push(ary, asn1data); + length -= len; + if(once) break; + } + *pp = p; + *offset = off; + + return ary; +} + +static VALUE +ossl_asn1_traverse(VALUE self, VALUE obj) +{ + unsigned char *p; + long offset = 0; + volatile VALUE tmp; + + obj = ossl_to_der_if_possible(obj); + tmp = rb_str_new4(StringValue(obj)); + p = RSTRING(tmp)->ptr; + ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1); + + return Qnil; +} + +static VALUE +ossl_asn1_decode(VALUE self, VALUE obj) +{ + VALUE ret, ary; + unsigned char *p; + long offset = 0; + volatile VALUE tmp; + + obj = ossl_to_der_if_possible(obj); + tmp = rb_str_new4(StringValue(obj)); + p = RSTRING(tmp)->ptr; + ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0); + ret = rb_ary_entry(ary, 0); + + return ret; +} + +static VALUE +ossl_asn1_decode_all(VALUE self, VALUE obj) +{ + VALUE ret; + unsigned char *p; + long offset = 0; + volatile VALUE tmp; + + obj = ossl_to_der_if_possible(obj); + tmp = rb_str_new4(StringValue(obj)); + p = RSTRING(tmp)->ptr; + ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0); + + return ret; +} + +static VALUE +ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE value, tag, tagging, tag_class; + + rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class); + if(argc > 1){ + if(NIL_P(tag)) + ossl_raise(eASN1Error, "must specify tag number"); + if(NIL_P(tagging)) + tagging = ID2SYM(sEXPLICIT); + if(!SYMBOL_P(tagging)) + ossl_raise(eASN1Error, "invalid tag default"); + if(NIL_P(tag_class)) + tag_class = ID2SYM(sCONTEXT_SPECIFIC); + if(!SYMBOL_P(tag_class)) + ossl_raise(eASN1Error, "invalid tag class"); + if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31) + ossl_raise(eASN1Error, "tag number for Universal too large"); + } + else{ + tag = INT2NUM(ossl_asn1_default_tag(self)); + tagging = Qnil; + tag_class = ID2SYM(sUNIVERSAL); + } + ossl_asn1_set_tag(self, tag); + ossl_asn1_set_value(self, value); + ossl_asn1_set_tagging(self, tagging); + ossl_asn1_set_tag_class(self, tag_class); + + return self; +} + +static int +ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp) +{ +#if OPENSSL_VERSION_NUMBER < 0x00907000L + if(!a) return 0; + if(a->type == V_ASN1_BOOLEAN) + return i2d_ASN1_BOOLEAN(a->value.boolean, pp); +#endif + return i2d_ASN1_TYPE(a, pp); +} + +static void +ossl_ASN1_TYPE_free(ASN1_TYPE *a) +{ +#if OPENSSL_VERSION_NUMBER < 0x00907000L + if(!a) return; + if(a->type == V_ASN1_BOOLEAN){ + OPENSSL_free(a); + return; + } +#endif + ASN1_TYPE_free(a); +} + +static VALUE +ossl_asn1prim_to_der(VALUE self) +{ + ASN1_TYPE *asn1; + int tn, tc, explicit; + long length, reallen; + unsigned char *buf, *p; + VALUE str; + + tn = NUM2INT(ossl_asn1_get_tag(self)); + tc = ossl_asn1_tag_class(self); + explicit = ossl_asn1_is_explicit(self); + asn1 = ossl_asn1_get_asn1type(self); + + length = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn); + if(!(buf = OPENSSL_malloc(length))){ + ossl_ASN1_TYPE_free(asn1); + ossl_raise(eASN1Error, "cannot alloc buffer"); + } + p = buf; + if(tc == V_ASN1_UNIVERSAL) ossl_i2d_ASN1_TYPE(asn1, &p); + else{ + if(explicit){ + ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc); + ossl_i2d_ASN1_TYPE(asn1, &p); + } + else{ + ossl_i2d_ASN1_TYPE(asn1, &p); + *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED); + } + } + ossl_ASN1_TYPE_free(asn1); + reallen = p - buf; + assert(reallen <= length); + str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */ + + return str; +} + +static VALUE +ossl_asn1cons_to_der(VALUE self) +{ + int tag, tn, tc, explicit; + long seq_len, length; + unsigned char *p; + VALUE value, str; + + tag = ossl_asn1_default_tag(self); + tn = NUM2INT(ossl_asn1_get_tag(self)); + tc = ossl_asn1_tag_class(self); + explicit = ossl_asn1_is_explicit(self); + value = join_der(ossl_asn1_get_value(self)); + + seq_len = ASN1_object_size(1, RSTRING(value)->len, tag); + length = ASN1_object_size(1, seq_len, tn); + str = rb_str_new(0, length); + p = RSTRING(str)->ptr; + if(tc == V_ASN1_UNIVERSAL) + ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc); + else{ + if(explicit){ + ASN1_put_object(&p, 1, seq_len, tn, tc); + ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL); + } + else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc); + } + memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len); + p += RSTRING(value)->len; + ossl_str_adjust(str, p); + + return str; +} + +static VALUE +ossl_asn1cons_each(VALUE self) +{ + rb_ary_each(ossl_asn1_get_value(self)); + return self; +} + +static VALUE +ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln) +{ + StringValue(oid); + StringValue(sn); + StringValue(ln); + + if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr)) + ossl_raise(eASN1Error, NULL); + + return Qtrue; +} + +static VALUE +ossl_asn1obj_get_sn(VALUE self) +{ + VALUE val, ret = Qnil; + int nid; + + val = ossl_asn1_get_value(self); + if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); + + return ret; +} + +static VALUE +ossl_asn1obj_get_ln(VALUE self) +{ + VALUE val, ret = Qnil; + int nid; + + val = ossl_asn1_get_value(self); + if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) + ret = rb_str_new2(OBJ_nid2ln(nid)); + + return ret; +} + +static VALUE +ossl_asn1obj_get_oid(VALUE self) +{ + VALUE val; + ASN1_OBJECT *a1obj; + char buf[128]; + + val = ossl_asn1_get_value(self); + a1obj = obj_to_asn1obj(val); + OBJ_obj2txt(buf, sizeof(buf), a1obj, 1); + ASN1_OBJECT_free(a1obj); + + return rb_str_new2(buf); +} + +#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ +static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\ +{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); } + +OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean) +OSSL_ASN1_IMPL_FACTORY_METHOD(Integer) +OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated) +OSSL_ASN1_IMPL_FACTORY_METHOD(BitString) +OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString) +OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String) +OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString) +OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString) +OSSL_ASN1_IMPL_FACTORY_METHOD(T61String) +OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString) +OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String) +OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString) +OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String) +OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString) +OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString) +OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString) +OSSL_ASN1_IMPL_FACTORY_METHOD(Null) +OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId) +OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime) +OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime) +OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence) +OSSL_ASN1_IMPL_FACTORY_METHOD(Set) + +void +Init_ossl_asn1() +{ + VALUE ary; + int i; + + sUNIVERSAL = rb_intern("UNIVERSAL"); + sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC"); + sAPPLICATION = rb_intern("APPLICATION"); + sPRIVATE = rb_intern("PRIVATE"); + sEXPLICIT = rb_intern("EXPLICIT"); + sIMPLICIT = rb_intern("IMPLICIT"); + + mASN1 = rb_define_module_under(mOSSL, "ASN1"); + eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError); + rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1); + rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1); + rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1); + ary = rb_ary_new(); + rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary); + for(i = 0; i < ossl_asn1_info_size; i++){ + if(ossl_asn1_info[i].name[0] == '[') continue; + rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i)); + rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name)); + } + + cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject); + rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue); + rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue); + rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue); + rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3); + rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0); + + cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data); + rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue); + rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1); + rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0); + + cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data); + rb_include_module(cASN1Constructive, rb_mEnumerable); + rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue); + rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1); + rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0); + rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0); + +#define OSSL_ASN1_DEFINE_CLASS(name, super) \ +do{\ + cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\ + rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\ +}while(0) + + OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive); + OSSL_ASN1_DEFINE_CLASS(Integer, Primitive); + OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive); + OSSL_ASN1_DEFINE_CLASS(BitString, Primitive); + OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive); + OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive); + OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive); + OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive); + OSSL_ASN1_DEFINE_CLASS(T61String, Primitive); + OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive); + OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive); + OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive); + OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive); + OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive); + OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive); + OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive); + OSSL_ASN1_DEFINE_CLASS(Null, Primitive); + OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive); + OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive); + OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive); + + OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive); + OSSL_ASN1_DEFINE_CLASS(Set, Constructive); + + rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3); + rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0); + rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0); + rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0); + rb_define_alias(cASN1ObjectId, "short_name", "sn"); + rb_define_alias(cASN1ObjectId, "long_name", "ln"); + rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_asn1.h b/ruby_1_8_5/ext/openssl/ossl_asn1.h new file mode 100644 index 0000000000..6a1c97b902 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_asn1.h @@ -0,0 +1,59 @@ +/* + * $Id: ossl_asn1.h,v 1.3.2.1 2005/09/10 01:17:00 gotoyuzo Exp $ + * 'OpenSSL for Ruby' team members + * Copyright (C) 2003 + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_ASN1_H_) +#define _OSSL_ASN1_H_ + +/* + * ASN1_DATE conversions + */ +VALUE asn1time_to_time(ASN1_TIME *); +time_t time_to_time_t(VALUE); + +/* + * ASN1_STRING conversions + */ +VALUE asn1str_to_str(ASN1_STRING *); + +/* + * ASN1_INTEGER conversions + */ +VALUE asn1integer_to_num(ASN1_INTEGER *); +ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *); + +/* + * ASN1 module + */ +extern VALUE mASN1; +extern VALUE eASN1Error; + +extern VALUE cASN1Data; +extern VALUE cASN1Primitive; +extern VALUE cASN1Constructive; + +extern VALUE cASN1Boolean; /* BOOLEAN */ +extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ +extern VALUE cASN1BitString; /* BIT STRING */ +extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ +extern VALUE cASN1NumericString, cASN1PrintableString; +extern VALUE cASN1T61String, cASN1VideotexString; +extern VALUE cASN1IA5String, cASN1GraphicString; +extern VALUE cASN1ISO64String, cASN1GeneralString; +extern VALUE cASN1UniversalString, cASN1BMPString; +extern VALUE cASN1Null; /* NULL */ +extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ +extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ +extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ + +ASN1_TYPE *ossl_asn1_get_asn1type(VALUE); + +void Init_ossl_asn1(void); + +#endif diff --git a/ruby_1_8_5/ext/openssl/ossl_bio.c b/ruby_1_8_5/ext/openssl/ossl_bio.c new file mode 100644 index 0000000000..4e3248eb1d --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_bio.c @@ -0,0 +1,73 @@ +/* + * $Id: ossl_bio.c,v 1.2.2.1 2005/06/19 16:29:17 gotoyuzo Exp $ + * 'OpenSSL for Ruby' team members + * Copyright (C) 2003 + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +BIO * +ossl_obj2bio(VALUE obj) +{ + BIO *bio; + + if (TYPE(obj) == T_FILE) { + OpenFile *fptr; + GetOpenFile(obj, fptr); + rb_io_check_readable(fptr); + bio = BIO_new_fp(fptr->f, BIO_NOCLOSE); + } + else { + StringValue(obj); + bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len); + } + if (!bio) ossl_raise(eOSSLError, NULL); + + return bio; +} + +BIO * +ossl_protect_obj2bio(VALUE obj, int *status) +{ + BIO *ret = NULL; + ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status); + return ret; +} + +VALUE +ossl_membio2str0(BIO *bio) +{ + VALUE ret; + BUF_MEM *buf; + + BIO_get_mem_ptr(bio, &buf); + ret = rb_str_new(buf->data, buf->length); + + return ret; +} + +VALUE +ossl_protect_membio2str(BIO *bio, int *status) +{ + return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status); +} + +VALUE +ossl_membio2str(BIO *bio) +{ + VALUE ret; + int status = 0; + + ret = ossl_protect_membio2str(bio, &status); + BIO_free(bio); + if(status) rb_jump_tag(status); + + return ret; +} diff --git a/ruby_1_8_5/ext/openssl/ossl_bio.h b/ruby_1_8_5/ext/openssl/ossl_bio.h new file mode 100644 index 0000000000..ca312679fa --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_bio.h @@ -0,0 +1,21 @@ +/* + * $Id: ossl_bio.h,v 1.2 2003/09/17 09:05:01 gotoyuzo Exp $ + * 'OpenSSL for Ruby' team members + * Copyright (C) 2003 + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_BIO_H_) +#define _OSSL_BIO_H_ + +BIO *ossl_obj2bio(VALUE); +BIO *ossl_protect_obj2bio(VALUE,int*); +VALUE ossl_membio2str0(BIO*); +VALUE ossl_membio2str(BIO*); +VALUE ossl_protect_membio2str(BIO*,int*); + +#endif + diff --git a/ruby_1_8_5/ext/openssl/ossl_bn.c b/ruby_1_8_5/ext/openssl/ossl_bn.c new file mode 100644 index 0000000000..fb86c8721c --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_bn.c @@ -0,0 +1,715 @@ +/* + * $Id: ossl_bn.c,v 1.5.2.1 2004/12/15 01:54:39 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Technorama team + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +/* modified by Michal Rokos */ +#include "ossl.h" + +#define WrapBN(klass, obj, bn) do { \ + if (!bn) { \ + ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, BN_clear_free, bn); \ +} while (0) + +#define GetBN(obj, bn) do { \ + Data_Get_Struct(obj, BIGNUM, bn); \ + if (!bn) { \ + ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ + } \ +} while (0) + +#define SafeGetBN(obj, bn) do { \ + OSSL_Check_Kind(obj, cBN); \ + GetBN(obj, bn); \ +} while (0) + +/* + * Classes + */ +VALUE cBN; +VALUE eBNError; + +/* + * Public + */ +VALUE +ossl_bn_new(BIGNUM *bn) +{ + BIGNUM *newbn; + VALUE obj; + + newbn = bn ? BN_dup(bn) : BN_new(); + if (!newbn) { + ossl_raise(eBNError, NULL); + } + WrapBN(cBN, obj, newbn); + + return obj; +} + +BIGNUM * +GetBNPtr(VALUE obj) +{ + BIGNUM *bn = NULL; + + if (RTEST(rb_obj_is_kind_of(obj, cBN))) { + GetBN(obj, bn); + } else switch (TYPE(obj)) { + case T_FIXNUM: + case T_BIGNUM: + obj = rb_String(obj); + if (!BN_dec2bn(&bn, StringValuePtr(obj))) { + ossl_raise(eBNError, NULL); + } + WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */ + break; + default: + ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); + } + return bn; +} + +/* + * Private + */ +/* + * BN_CTX - is used in more difficult math. ops + * (Why just 1? Because Ruby itself isn't thread safe, + * we don't need to care about threads) + */ +BN_CTX *ossl_bn_ctx; + +static VALUE +ossl_bn_alloc(VALUE klass) +{ + BIGNUM *bn; + VALUE obj; + + if (!(bn = BN_new())) { + ossl_raise(eBNError, NULL); + } + WrapBN(klass, obj, bn); + + return obj; +} + +static VALUE +ossl_bn_initialize(int argc, VALUE *argv, VALUE self) +{ + BIGNUM *bn; + VALUE str, bs; + int base = 10; + + if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) { + base = NUM2INT(bs); + } + StringValue(str); + GetBN(self, bn); + if (RTEST(rb_obj_is_kind_of(str, cBN))) { + BIGNUM *other; + + GetBN(str, other); /* Safe - we checked kind_of? above */ + if (!BN_copy(bn, other)) { + ossl_raise(eBNError, NULL); + } + return self; + } + + switch (base) { + case 0: + if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) { + ossl_raise(eBNError, NULL); + } + break; + case 2: + if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) { + ossl_raise(eBNError, NULL); + } + break; + case 10: + if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) { + ossl_raise(eBNError, NULL); + } + break; + case 16: + if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) { + ossl_raise(eBNError, NULL); + } + break; + default: + ossl_raise(rb_eArgError, "illegal radix %d", base); + } + return self; +} + +static VALUE +ossl_bn_to_s(int argc, VALUE *argv, VALUE self) +{ + BIGNUM *bn; + VALUE str, bs; + int base = 10, len; + char *buf; + + if (rb_scan_args(argc, argv, "01", &bs) == 1) { + base = NUM2INT(bs); + } + GetBN(self, bn); + switch (base) { + case 0: + len = BN_bn2mpi(bn, NULL); + str = rb_str_new(0, len); + if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len) + ossl_raise(eBNError, NULL); + break; + case 2: + len = BN_num_bytes(bn); + str = rb_str_new(0, len); + if (BN_bn2bin(bn, RSTRING(str)->ptr) != len) + ossl_raise(eBNError, NULL); + break; + case 10: + if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, strlen(buf)); + break; + case 16: + if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, strlen(buf)); + break; + default: + ossl_raise(rb_eArgError, "illegal radix %d", base); + } + + return str; +} + +static VALUE +ossl_bn_to_i(VALUE self) +{ + BIGNUM *bn; + char *txt; + VALUE num; + + GetBN(self, bn); + + if (!(txt = BN_bn2dec(bn))) { + ossl_raise(eBNError, NULL); + } + num = rb_cstr_to_inum(txt, 10, Qtrue); + OPENSSL_free(txt); + + return num; +} + +static VALUE +ossl_bn_to_bn(VALUE self) +{ + return self; +} + +static VALUE +ossl_bn_coerce(VALUE self, VALUE other) +{ + switch(TYPE(other)) { + case T_STRING: + self = ossl_bn_to_s(0, NULL, self); + break; + case T_FIXNUM: + case T_BIGNUM: + self = ossl_bn_to_i(self); + break; + default: + if (!RTEST(rb_obj_is_kind_of(other, cBN))) { + ossl_raise(rb_eTypeError, "Don't know how to coerce"); + } + } + return rb_assoc_new(other, self); +} + +#define BIGNUM_BOOL1(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn; \ + GetBN(self, bn); \ + if (BN_##func(bn)) { \ + return Qtrue; \ + } \ + return Qfalse; \ + } +BIGNUM_BOOL1(is_zero); +BIGNUM_BOOL1(is_one); +BIGNUM_BOOL1(is_odd); + +#define BIGNUM_1c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn, *result; \ + VALUE obj; \ + GetBN(self, bn); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, bn, ossl_bn_ctx)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(CLASS_OF(self), obj, result); \ + return obj; \ + } +BIGNUM_1c(sqr); + +#define BIGNUM_2(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, bn1, bn2)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(CLASS_OF(self), obj, result); \ + return obj; \ + } +BIGNUM_2(add); +BIGNUM_2(sub); + +#define BIGNUM_2c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(CLASS_OF(self), obj, result); \ + return obj; \ + } +BIGNUM_2c(mul); +BIGNUM_2c(mod); +BIGNUM_2c(exp); +BIGNUM_2c(gcd); +BIGNUM_2c(mod_sqr); +BIGNUM_2c(mod_inverse); + +static VALUE +ossl_bn_div(VALUE self, VALUE other) +{ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2; + VALUE obj1, obj2; + + GetBN(self, bn1); + + if (!(r1 = BN_new())) { + ossl_raise(eBNError, NULL); + } + if (!(r2 = BN_new())) { + BN_free(r1); + ossl_raise(eBNError, NULL); + } + if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) { + BN_free(r1); + BN_free(r2); + ossl_raise(eBNError, NULL); + } + WrapBN(CLASS_OF(self), obj1, r1); + WrapBN(CLASS_OF(self), obj2, r2); + + return rb_ary_new3(2, obj1, obj2); +} + +#define BIGNUM_3c(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other1); \ + BIGNUM *bn3 = GetBNPtr(other2), *result; \ + VALUE obj; \ + GetBN(self, bn1); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(CLASS_OF(self), obj, result); \ + return obj; \ + } +BIGNUM_3c(mod_add); +BIGNUM_3c(mod_sub); +BIGNUM_3c(mod_mul); +BIGNUM_3c(mod_exp); + +#define BIGNUM_BIT(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE bit) \ + { \ + BIGNUM *bn; \ + GetBN(self, bn); \ + if (!BN_##func(bn, NUM2INT(bit))) { \ + ossl_raise(eBNError, NULL); \ + } \ + return self; \ + } +BIGNUM_BIT(set_bit); +BIGNUM_BIT(clear_bit); +BIGNUM_BIT(mask_bits); + +static VALUE +ossl_bn_is_bit_set(VALUE self, VALUE bit) +{ + int b; + BIGNUM *bn; + + b = NUM2INT(bit); + GetBN(self, bn); + if (BN_is_bit_set(bn, b)) { + return Qtrue; + } + return Qfalse; +} + +#define BIGNUM_SHIFT(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE bits) \ + { \ + BIGNUM *bn, *result; \ + int b; \ + VALUE obj; \ + b = NUM2INT(bits); \ + GetBN(self, bn); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, bn, b)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(CLASS_OF(self), obj, result); \ + return obj; \ + } +BIGNUM_SHIFT(lshift); +BIGNUM_SHIFT(rshift); + +#define BIGNUM_RAND(func) \ + static VALUE \ + ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ + { \ + BIGNUM *result; \ + int bottom = 0, top = 0, b; \ + VALUE bits, fill, odd, obj; \ + \ + switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ + case 3: \ + bottom = (odd == Qtrue) ? 1 : 0; \ + /* FALLTHROUGH */ \ + case 2: \ + top = FIX2INT(fill); \ + } \ + b = NUM2INT(bits); \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func(result, b, top, bottom)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(klass, obj, result); \ + return obj; \ + } +BIGNUM_RAND(rand); +BIGNUM_RAND(pseudo_rand); + +#define BIGNUM_RAND_RANGE(func) \ + static VALUE \ + ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ + { \ + BIGNUM *bn = GetBNPtr(range), *result; \ + VALUE obj; \ + if (!(result = BN_new())) { \ + ossl_raise(eBNError, NULL); \ + } \ + if (!BN_##func##_range(result, bn)) { \ + BN_free(result); \ + ossl_raise(eBNError, NULL); \ + } \ + WrapBN(klass, obj, result); \ + return obj; \ + } +BIGNUM_RAND_RANGE(rand); +BIGNUM_RAND_RANGE(pseudo_rand); + +static VALUE +ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) +{ + BIGNUM *add = NULL, *rem = NULL, *result; + int safe = 1, num; + VALUE vnum, vsafe, vadd, vrem, obj; + + rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem); + + num = NUM2INT(vnum); + + if (vsafe == Qfalse) { + safe = 0; + } + if (!NIL_P(vadd)) { + if (NIL_P(vrem)) { + ossl_raise(rb_eArgError, + "if ADD is specified, REM must be also given"); + } + add = GetBNPtr(vadd); + rem = GetBNPtr(vrem); + } + if (!(result = BN_new())) { + ossl_raise(eBNError, NULL); + } + if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) { + BN_free(result); + ossl_raise(eBNError, NULL); + } + WrapBN(klass, obj, result); + + return obj; +} + +#define BIGNUM_NUM(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + BIGNUM *bn; \ + GetBN(self, bn); \ + return INT2FIX(BN_##func(bn)); \ + } +BIGNUM_NUM(num_bytes); +BIGNUM_NUM(num_bits); + +static VALUE +ossl_bn_copy(VALUE self, VALUE other) +{ + BIGNUM *bn1, *bn2; + + rb_check_frozen(self); + + if (self == other) return self; + + GetBN(self, bn1); + bn2 = GetBNPtr(other); + + if (!BN_copy(bn1, bn2)) { + ossl_raise(eBNError, NULL); + } + return self; +} + +#define BIGNUM_CMP(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + BIGNUM *bn1, *bn2 = GetBNPtr(other); \ + GetBN(self, bn1); \ + return INT2FIX(BN_##func(bn1, bn2)); \ + } +BIGNUM_CMP(cmp); +BIGNUM_CMP(ucmp); + +static VALUE +ossl_bn_eql(VALUE self, VALUE other) +{ + if (ossl_bn_cmp(self, other) == INT2FIX(0)) { + return Qtrue; + } + return Qfalse; +} + +static VALUE +ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) +{ + BIGNUM *bn; + VALUE vchecks; + int checks = BN_prime_checks; + + if (rb_scan_args(argc, argv, "01", &vchecks) == 0) { + checks = NUM2INT(vchecks); + } + GetBN(self, bn); + switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) { + case 1: + return Qtrue; + case 0: + return Qfalse; + default: + ossl_raise(eBNError, NULL); + } + /* not reachable */ + return Qnil; +} + +static VALUE +ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) +{ + BIGNUM *bn; + VALUE vchecks, vtrivdiv; + int checks = BN_prime_checks, do_trial_division = 1; + + rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); + + if (!NIL_P(vchecks)) { + checks = NUM2INT(vchecks); + } + GetBN(self, bn); + /* handle true/false */ + if (vtrivdiv == Qfalse) { + do_trial_division = 0; + } + switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) { + case 1: + return Qtrue; + case 0: + return Qfalse; + default: + ossl_raise(eBNError, NULL); + } + /* not reachable */ + return Qnil; +} + +/* + * INIT + * (NOTE: ordering of methods is the same as in 'man bn') + */ +void +Init_ossl_bn() +{ + if (!(ossl_bn_ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + + eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); + + cBN = rb_define_class_under(mOSSL, "BN", rb_cObject); + + rb_define_alloc_func(cBN, ossl_bn_alloc); + rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); + + rb_define_copy_func(cBN, ossl_bn_copy); + rb_define_method(cBN, "copy", ossl_bn_copy, 1); + + /* swap (=coerce?) */ + + rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0); + rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); + /* num_bits_word */ + + rb_define_method(cBN, "+", ossl_bn_add, 1); + rb_define_method(cBN, "-", ossl_bn_sub, 1); + rb_define_method(cBN, "*", ossl_bn_mul, 1); + rb_define_method(cBN, "sqr", ossl_bn_sqr, 0); + rb_define_method(cBN, "/", ossl_bn_div, 1); + rb_define_method(cBN, "%", ossl_bn_mod, 1); + /* nnmod */ + + rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2); + rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2); + rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2); + rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1); + rb_define_method(cBN, "**", ossl_bn_exp, 1); + rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2); + rb_define_method(cBN, "gcd", ossl_bn_gcd, 1); + + /* add_word + * sub_word + * mul_word + * div_word + * mod_word */ + + rb_define_method(cBN, "cmp", ossl_bn_cmp, 1); + rb_define_alias(cBN, "<=>", "cmp"); + rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); + rb_define_method(cBN, "eql?", ossl_bn_eql, 1); + rb_define_alias(cBN, "==", "eql?"); + rb_define_alias(cBN, "===", "eql?"); + rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); + rb_define_method(cBN, "one?", ossl_bn_is_one, 0); + /* is_word */ + rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); + + /* zero + * one + * value_one - DON'T IMPL. + * set_word + * get_word */ + + rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); + rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); + rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); + rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); + + rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); + rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); + + rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1); + rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1); + rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1); + rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1); + rb_define_method(cBN, "<<", ossl_bn_lshift, 1); + /* lshift1 - DON'T IMPL. */ + rb_define_method(cBN, ">>", ossl_bn_rshift, 1); + /* rshift1 - DON'T IMPL. */ + + /* + * bn2bin + * bin2bn + * bn2hex + * bn2dec + * hex2bn + * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s + * print - NOT IMPL. + * print_fp - NOT IMPL. + * bn2mpi + * mpi2bn + */ + rb_define_method(cBN, "to_s", ossl_bn_to_s, -1); + rb_define_method(cBN, "to_i", ossl_bn_to_i, 0); + rb_define_alias(cBN, "to_int", "to_i"); + rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0); + rb_define_method(cBN, "coerce", ossl_bn_coerce, 1); + + /* + * TODO: + * But how to: from_bin, from_mpi? PACK? + * to_bin + * to_mpi + */ + + rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1); + + /* RECiProcal + * MONTgomery */ + + /* + * TODO: + * Where to belong these? + */ + rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_bn.h b/ruby_1_8_5/ext/openssl/ossl_bn.h new file mode 100644 index 0000000000..bccdbc0cd6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_bn.h @@ -0,0 +1,22 @@ +/* + * $Id: ossl_bn.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_BN_H_) +#define _OSSL_BN_H_ + +extern VALUE cBN; +extern VALUE eBNError; + +VALUE ossl_bn_new(BIGNUM *); +BIGNUM *GetBNPtr(VALUE); +void Init_ossl_bn(void); + +#endif /* _OSS_BN_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_cipher.c b/ruby_1_8_5/ext/openssl/ossl_cipher.c new file mode 100644 index 0000000000..8d96d0b35a --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_cipher.c @@ -0,0 +1,406 @@ +/* + * $Id: ossl_cipher.c,v 1.4.2.6 2006/06/20 11:18:15 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define MakeCipher(obj, klass, ctx) \ + obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx) +#define GetCipher(obj, ctx) do { \ + Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \ + } \ +} while (0) +#define SafeGetCipher(obj, ctx) do { \ + OSSL_Check_Kind(obj, cCipher); \ + GetCipher(obj, ctx); \ +} while (0) + +/* + * Classes + */ +VALUE mCipher; +VALUE cCipher; +VALUE eCipherError; + +static VALUE ossl_cipher_alloc(VALUE klass); + +/* + * PUBLIC + */ +const EVP_CIPHER * +GetCipherPtr(VALUE obj) +{ + EVP_CIPHER_CTX *ctx; + + SafeGetCipher(obj, ctx); + + return EVP_CIPHER_CTX_cipher(ctx); +} + +VALUE +ossl_cipher_new(const EVP_CIPHER *cipher) +{ + VALUE ret; + EVP_CIPHER_CTX *ctx; + + ret = ossl_cipher_alloc(cCipher); + GetCipher(ret, ctx); + EVP_CIPHER_CTX_init(ctx); + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1) + ossl_raise(eCipherError, NULL); + + return ret; +} + +/* + * PRIVATE + */ +static void +ossl_cipher_free(EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + EVP_CIPHER_CTX_cleanup(ctx); + free(ctx); + } +} + +static VALUE +ossl_cipher_alloc(VALUE klass) +{ + EVP_CIPHER_CTX *ctx; + VALUE obj; + + MakeCipher(obj, klass, ctx); + EVP_CIPHER_CTX_init(ctx); + + return obj; +} + +static VALUE +ossl_cipher_initialize(VALUE self, VALUE str) +{ + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + char *name; + + name = StringValuePtr(str); + GetCipher(self, ctx); + if (!(cipher = EVP_get_cipherbyname(name))) { + ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name); + } + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1) + ossl_raise(eCipherError, NULL); + + return self; +} +static VALUE +ossl_cipher_copy(VALUE self, VALUE other) +{ + EVP_CIPHER_CTX *ctx1, *ctx2; + + rb_check_frozen(self); + if (self == other) return self; + + GetCipher(self, ctx1); + SafeGetCipher(other, ctx2); + if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1) + ossl_raise(eCipherError, NULL); + + return self; +} + +static void* +add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary) +{ + rb_ary_push(ary, rb_str_new2(name->name)); + return NULL; +} + +static VALUE +ossl_s_ciphers(VALUE self) +{ +#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED + VALUE ary; + + ary = rb_ary_new(); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, + (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary, + (void*)ary); + + return ary; +#else + rb_notimplement(); +#endif +} + +static VALUE +ossl_cipher_reset(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1) + ossl_raise(eCipherError, NULL); + + return self; +} + +static VALUE +ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) +{ + EVP_CIPHER_CTX *ctx; + unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; + VALUE pass, init_v; + + if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ + /* + * oops. this code mistakes salt for IV. + * We deprecated the arguments for this method, but we decided + * keeping this behaviour for backward compatibility. + */ + StringValue(pass); + GetCipher(self, ctx); + if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); + else{ + char *cname = rb_class2name(rb_obj_class(self)); + rb_warning("key derivation by %s#encrypt is deprecated; " + "use %s::pkcs5_keyivgen instead", cname, cname); + StringValue(init_v); + if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) { + memset(iv, 0, EVP_MAX_IV_LENGTH); + memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len); + } + else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv)); + } + EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, + RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); + p_key = key; + p_iv = iv; + } + else { + GetCipher(self, ctx); + } + if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { + ossl_raise(eCipherError, NULL); + } + + return self; +} + +static VALUE +ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) +{ + return ossl_cipher_init(argc, argv, self, 1); +} + +static VALUE +ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) +{ + return ossl_cipher_init(argc, argv, self, 0); +} + +static VALUE +ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) +{ + EVP_CIPHER_CTX *ctx; + const EVP_MD *digest; + VALUE vpass, vsalt, viter, vdigest; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL; + int iter; + + rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest); + StringValue(vpass); + if(!NIL_P(vsalt)){ + StringValue(vsalt); + if(RSTRING(vsalt)->len != PKCS5_SALT_LEN) + rb_raise(eCipherError, "salt must be an 8-octet string"); + salt = RSTRING(vsalt)->ptr; + } + iter = NIL_P(viter) ? 2048 : NUM2INT(viter); + digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest); + GetCipher(self, ctx); + EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt, + RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv); + if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1) + ossl_raise(eCipherError, NULL); + OPENSSL_cleanse(key, sizeof key); + OPENSSL_cleanse(iv, sizeof iv); + + return Qnil; +} + +static VALUE +ossl_cipher_update(VALUE self, VALUE data) +{ + EVP_CIPHER_CTX *ctx; + char *in; + int in_len, out_len; + VALUE str; + + StringValue(data); + in = RSTRING(data)->ptr; + if ((in_len = RSTRING(data)->len) == 0) + rb_raise(rb_eArgError, "data must not be empty"); + GetCipher(self, ctx); + str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx)); + if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len)) + ossl_raise(eCipherError, NULL); + assert(out_len < RSTRING(str)->len); + RSTRING(str)->len = out_len; + RSTRING(str)->ptr[out_len] = 0; + + return str; +} + +static VALUE +ossl_cipher_update_deprecated(VALUE self, VALUE data) +{ + char *cname; + + cname = rb_class2name(rb_obj_class(self)); + rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname); + return ossl_cipher_update(self, data); +} + +static VALUE +ossl_cipher_final(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + int out_len; + VALUE str; + + GetCipher(self, ctx); + str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx)); + if (!EVP_CipherFinal_ex(ctx, RSTRING(str)->ptr, &out_len)) + ossl_raise(eCipherError, NULL); + assert(out_len <= RSTRING(str)->len); + RSTRING(str)->len = out_len; + RSTRING(str)->ptr[out_len] = 0; + + return str; +} + +static VALUE +ossl_cipher_name(VALUE self) +{ + EVP_CIPHER_CTX *ctx; + + GetCipher(self, ctx); + + return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx))); +} + +static VALUE +ossl_cipher_set_key(VALUE self, VALUE key) +{ + EVP_CIPHER_CTX *ctx; + + StringValue(key); + GetCipher(self, ctx); + + if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx)) + ossl_raise(eCipherError, "key length too short"); + + if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING(key)->ptr, NULL, -1) != 1) + ossl_raise(eCipherError, NULL); + + return key; +} + +static VALUE +ossl_cipher_set_iv(VALUE self, VALUE iv) +{ + EVP_CIPHER_CTX *ctx; + + StringValue(iv); + GetCipher(self, ctx); + + if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx)) + ossl_raise(eCipherError, "iv length too short"); + + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1) + ossl_raise(eCipherError, NULL); + + return iv; +} + +static VALUE +ossl_cipher_set_key_length(VALUE self, VALUE key_length) +{ + EVP_CIPHER_CTX *ctx; + int len = NUM2INT(key_length); + + GetCipher(self, ctx); + if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1) + ossl_raise(eCipherError, NULL); + + return key_length; +} + +static VALUE +ossl_cipher_set_padding(VALUE self, VALUE padding) +{ +#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING) + EVP_CIPHER_CTX *ctx; + int pad = NUM2INT(padding); + + GetCipher(self, ctx); + if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1) + ossl_raise(eCipherError, NULL); +#else + rb_notimplement(); +#endif + return padding; +} + +#define CIPHER_0ARG_INT(func) \ + static VALUE \ + ossl_cipher_##func(VALUE self) \ + { \ + EVP_CIPHER_CTX *ctx; \ + GetCipher(self, ctx); \ + return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \ + } +CIPHER_0ARG_INT(key_length) +CIPHER_0ARG_INT(iv_length) +CIPHER_0ARG_INT(block_size) + +/* + * INIT + */ +void +Init_ossl_cipher(void) +{ + mCipher = rb_define_module_under(mOSSL, "Cipher"); + eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError); + cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject); + + rb_define_alloc_func(cCipher, ossl_cipher_alloc); + rb_define_copy_func(cCipher, ossl_cipher_copy); + rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0); + rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); + rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); + rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); + rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); + rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); + rb_define_method(cCipher, "update", ossl_cipher_update, 1); + rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1); + rb_define_method(cCipher, "final", ossl_cipher_final, 0); + rb_define_method(cCipher, "name", ossl_cipher_name, 0); + rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1); + rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1); + rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0); + rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1); + rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); + rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); + rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_cipher.h b/ruby_1_8_5/ext/openssl/ossl_cipher.h new file mode 100644 index 0000000000..870927c37c --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_cipher.h @@ -0,0 +1,23 @@ +/* + * $Id: ossl_cipher.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_CIPHER_H_) +#define _OSSL_CIPHER_H_ + +extern VALUE mCipher; +extern VALUE cCipher; +extern VALUE eCipherError; + +const EVP_CIPHER *GetCipherPtr(VALUE); +VALUE ossl_cipher_new(const EVP_CIPHER *); +void Init_ossl_cipher(void); + +#endif /* _OSSL_CIPHER_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_config.c b/ruby_1_8_5/ext/openssl/ossl_config.c new file mode 100644 index 0000000000..64998bb86a --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_config.c @@ -0,0 +1,462 @@ +/* + * $Id: ossl_config.c,v 1.8.2.3 2004/12/15 01:54:39 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapConfig(klass, obj, conf) do { \ + if (!conf) { \ + ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \ +} while (0) +#define GetConfig(obj, conf) do { \ + Data_Get_Struct(obj, CONF, conf); \ + if (!conf) { \ + ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \ + } \ +} while (0) +#define SafeGetConfig(obj, conf) do { \ + OSSL_Check_Kind(obj, cConfig); \ + GetConfig(obj, conf); \ +} while(0); + +/* + * Classes + */ +VALUE cConfig; +VALUE eConfigError; + +/* + * Public + */ + +static CONF *parse_config(VALUE, CONF*); + +CONF * +GetConfigPtr(VALUE obj) +{ + CONF *conf; + + SafeGetConfig(obj, conf); + + return conf; +} + +CONF * +DupConfigPtr(VALUE obj) +{ + VALUE str; + + OSSL_Check_Kind(obj, cConfig); + str = rb_funcall(obj, rb_intern("to_s"), 0); + + return parse_config(str, NULL); +} + +/* + * Private + */ +static CONF * +parse_config(VALUE str, CONF *dst) +{ + CONF *conf; + BIO *bio; + long eline = -1; + + bio = ossl_obj2bio(str); + conf = dst ? dst : NCONF_new(NULL); + if(!conf){ + BIO_free(bio); + ossl_raise(eConfigError, NULL); + } + if(!NCONF_load_bio(conf, bio, &eline)){ + BIO_free(bio); + if(!dst) NCONF_free(conf); + if (eline <= 0) ossl_raise(eConfigError, "wrong config format"); + else ossl_raise(eConfigError, "error in line %d", eline); + ossl_raise(eConfigError, NULL); + } + BIO_free(bio); + + return conf; +} + +static VALUE +ossl_config_s_parse(VALUE klass, VALUE str) +{ + CONF *conf; + VALUE obj; + + conf = parse_config(str, NULL); + WrapConfig(klass, obj, conf); + + return obj; +} + +static VALUE +ossl_config_s_alloc(VALUE klass) +{ + CONF *conf; + VALUE obj; + + if(!(conf = NCONF_new(NULL))) + ossl_raise(eConfigError, NULL); + WrapConfig(klass, obj, conf); + + return obj; +} + +static VALUE +ossl_config_copy(VALUE self, VALUE other) +{ + VALUE str; + CONF *conf; + + str = rb_funcall(self, rb_intern("to_s"), 0); + GetConfig(other, conf); + parse_config(str, conf); + + return self; +} + +static VALUE +ossl_config_initialize(int argc, VALUE *argv, VALUE self) +{ + CONF *conf; + long eline = -1; + char *filename; + VALUE path; + + rb_scan_args(argc, argv, "01", &path); + if(!NIL_P(path)){ + SafeStringValue(path); + filename = StringValuePtr(path); + GetConfig(self, conf); + if (!NCONF_load(conf, filename, &eline)){ + if (eline <= 0) + ossl_raise(eConfigError, "wrong config file %s", filename); + else + ossl_raise(eConfigError, "error in %s:%d", filename, eline); + } + } +#ifdef OSSL_NO_CONF_API + else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)"); +#else + else { + GetConfig(self, conf); + _CONF_new_data(conf); + } +#endif + + return self; +} + +static VALUE +ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value) +{ +#ifdef OSSL_NO_CONF_API + rb_notimplement(); +#else + CONF *conf; + CONF_VALUE *sv, *cv; + + StringValue(section); + StringValue(name); + StringValue(value); + GetConfig(self, conf); + if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){ + if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){ + ossl_raise(eConfigError, NULL); + } + } + if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){ + ossl_raise(eConfigError, NULL); + } + cv->name = BUF_strdup(RSTRING(name)->ptr); + cv->value = BUF_strdup(RSTRING(value)->ptr); + if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){ + OPENSSL_free(cv->name); + OPENSSL_free(cv->value); + OPENSSL_free(cv); + ossl_raise(eConfigError, "_CONF_add_string failure"); + } + + return value; +#endif +} + +static VALUE +ossl_config_get_value(VALUE self, VALUE section, VALUE name) +{ + CONF *conf; + char *str; + + StringValue(section); + StringValue(name); + GetConfig(self, conf); + str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr); + if(!str){ + ERR_clear_error(); + return Qnil; + } + + return rb_str_new2(str); +} + +static VALUE +ossl_config_get_value_old(int argc, VALUE *argv, VALUE self) +{ + VALUE section, name; + + rb_scan_args(argc, argv, "11", §ion, &name); + + /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */ + if (NIL_P(section)) section = rb_str_new2(""); + /* support conf.value("HOME") -> conf.get_value("", "HOME") */ + if (NIL_P(name)) { + name = section; + section = rb_str_new2(""); + } + /* NOTE: Don't care about conf.get_value(nil, nil) */ + rb_warn("Config#value is deprecated; use Config#get_value"); + return ossl_config_get_value(self, section, name); +} + +static VALUE +set_conf_section_i(VALUE i, VALUE *arg) +{ + VALUE name, value; + + Check_Type(i, T_ARRAY); + name = rb_ary_entry(i, 0); + value = rb_ary_entry(i, 1); + ossl_config_add_value(arg[0], arg[1], name, value); + + return Qnil; +} + +static VALUE +ossl_config_set_section(VALUE self, VALUE section, VALUE hash) +{ + VALUE arg[2]; + + arg[0] = self; + arg[1] = section; + rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg); + return hash; +} + +/* + * Get all numbers as strings - use str.to_i to convert + * long number = CONF_get_number(confp->config, sect, StringValuePtr(item)); + */ +static VALUE +ossl_config_get_section(VALUE self, VALUE section) +{ + CONF *conf; + STACK_OF(CONF_VALUE) *sk; + CONF_VALUE *entry; + int i, entries; + VALUE hash; + + hash = rb_hash_new(); + StringValue(section); + GetConfig(self, conf); + if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) { + ERR_clear_error(); + return hash; + } + if ((entries = sk_CONF_VALUE_num(sk)) < 0) { + OSSL_Debug("# of items in section is < 0?!?"); + return hash; + } + for (i=0; iname), rb_str_new2(entry->value)); + } + + return hash; +} + +static VALUE +ossl_config_get_section_old(VALUE self, VALUE section) +{ + rb_warn("Config#section is deprecated; use Config#[]"); + return ossl_config_get_section(self, section); +} + +#ifdef IMPLEMENT_LHASH_DOALL_ARG_FN +static void +get_conf_section(CONF_VALUE *cv, VALUE ary) +{ + if(cv->name) return; + rb_ary_push(ary, rb_str_new2(cv->section)); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE*, VALUE); + +static VALUE +ossl_config_get_sections(VALUE self) +{ + CONF *conf; + VALUE ary; + + GetConfig(self, conf); + ary = rb_ary_new(); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(get_conf_section), (void*)ary); + + return ary; +} + +static void +dump_conf_value(CONF_VALUE *cv, VALUE str) +{ + STACK_OF(CONF_VALUE) *sk; + CONF_VALUE *v; + int i, num; + + if (cv->name) return; + sk = (STACK_OF(CONF_VALUE)*)cv->value; + num = sk_CONF_VALUE_num(sk); + rb_str_cat2(str, "[ "); + rb_str_cat2(str, cv->section); + rb_str_cat2(str, " ]\n"); + for(i = 0; i < num; i++){ + v = sk_CONF_VALUE_value(sk, i); + rb_str_cat2(str, v->name ? v->name : "None"); + rb_str_cat2(str, "="); + rb_str_cat2(str, v->value ? v->value : "None"); + rb_str_cat2(str, "\n"); + } + rb_str_cat2(str, "\n"); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE*, VALUE); + +static VALUE +dump_conf(CONF *conf) +{ + VALUE str; + + str = rb_str_new(0, 0); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), (void*)str); + + return str; +} + +static VALUE +ossl_config_to_s(VALUE self) +{ + CONF *conf; + + GetConfig(self, conf); + + return dump_conf(conf); +} + +static void +each_conf_value(CONF_VALUE *cv, void* dummy) +{ + STACK_OF(CONF_VALUE) *sk; + CONF_VALUE *v; + VALUE section, name, value, args; + int i, num; + + if (cv->name) return; + sk = (STACK_OF(CONF_VALUE)*)cv->value; + num = sk_CONF_VALUE_num(sk); + section = rb_str_new2(cv->section); + for(i = 0; i < num; i++){ + v = sk_CONF_VALUE_value(sk, i); + name = v->name ? rb_str_new2(v->name) : Qnil; + value = v->value ? rb_str_new2(v->value) : Qnil; + args = rb_ary_new3(3, section, name, value); + rb_yield(args); + } +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE*, void*); + +static VALUE +ossl_config_each(VALUE self) +{ + CONF *conf; + + GetConfig(self, conf); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(each_conf_value), (void*)NULL); + + return self; +} +#else +static VALUE +ossl_config_get_sections(VALUE self) +{ + rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT); + return rb_ary_new(); +} + +static VALUE +ossl_config_to_s(VALUE self) +{ + rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT); + return rb_str_new(0, 0); +} + +static VALUE +ossl_config_each(VALUE self) +{ + rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT); + return self; +} +#endif + +static VALUE +ossl_config_inspect(VALUE self) +{ + VALUE str, ary = ossl_config_get_sections(self); + char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new2("#<"); + rb_str_cat2(str, cname); + rb_str_cat2(str, " sections="); + rb_str_append(str, rb_inspect(ary)); + rb_str_cat2(str, ">"); + + return str; +} + +/* + * INIT + */ +void +Init_ossl_config() +{ + eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); + cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); + + rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", + rb_str_new2(CONF_get1_default_config_file())); + rb_include_module(cConfig, rb_mEnumerable); + rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1); + rb_define_alias(CLASS_OF(cConfig), "load", "new"); + rb_define_alloc_func(cConfig, ossl_config_s_alloc); + rb_define_copy_func(cConfig, ossl_config_copy); + rb_define_method(cConfig, "initialize", ossl_config_initialize, -1); + rb_define_method(cConfig, "get_value", ossl_config_get_value, 2); + rb_define_method(cConfig, "value", ossl_config_get_value_old, -1); + rb_define_method(cConfig, "add_value", ossl_config_add_value, 3); + rb_define_method(cConfig, "[]", ossl_config_get_section, 1); + rb_define_method(cConfig, "section", ossl_config_get_section_old, 1); + rb_define_method(cConfig, "[]=", ossl_config_set_section, 2); + rb_define_method(cConfig, "sections", ossl_config_get_sections, 0); + rb_define_method(cConfig, "to_s", ossl_config_to_s, 0); + rb_define_method(cConfig, "each", ossl_config_each, 0); + rb_define_method(cConfig, "inspect", ossl_config_inspect, 0); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_config.h b/ruby_1_8_5/ext/openssl/ossl_config.h new file mode 100644 index 0000000000..452d430b5e --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_config.h @@ -0,0 +1,22 @@ +/* + * $Id: ossl_config.h,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_CONFIG_H_) +#define _OSSL_CONFIG_H_ + +extern VALUE cConfig; +extern VALUE eConfigError; + +CONF* GetConfigPtr(VALUE obj); +CONF* DupConfigPtr(VALUE obj); +void Init_ossl_config(void); + +#endif /* _OSSL_CONFIG_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_digest.c b/ruby_1_8_5/ext/openssl/ossl_digest.c new file mode 100644 index 0000000000..8b9c273f4d --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_digest.c @@ -0,0 +1,294 @@ +/* + * $Id: ossl_digest.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define GetDigest(obj, ctx) do { \ + Data_Get_Struct(obj, EVP_MD_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetDigest(obj, ctx) do { \ + OSSL_Check_Kind(obj, cDigest); \ + GetDigest(obj, ctx); \ +} while (0) + +/* + * Classes + */ +VALUE mDigest; +VALUE cDigest; +VALUE eDigestError; + +static VALUE ossl_digest_alloc(VALUE klass); + +/* + * Public + */ +const EVP_MD * +GetDigestPtr(VALUE obj) +{ + EVP_MD_CTX *ctx; + + SafeGetDigest(obj, ctx); + + return EVP_MD_CTX_md(ctx); /*== ctx->digest*/ +} + +VALUE +ossl_digest_new(const EVP_MD *md) +{ + VALUE ret; + EVP_MD_CTX *ctx; + + ret = ossl_digest_alloc(cDigest); + GetDigest(ret, ctx); + EVP_MD_CTX_init(ctx); + EVP_DigestInit_ex(ctx, md, NULL); + + return ret; +} + +/* + * Private + */ +static VALUE +ossl_digest_alloc(VALUE klass) +{ + EVP_MD_CTX *ctx; + VALUE obj; + + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) + ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed"); + EVP_MD_CTX_init(ctx); + obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx); + + return obj; +} + +VALUE ossl_digest_update(VALUE, VALUE); + +static VALUE +ossl_digest_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_MD_CTX *ctx; + const EVP_MD *md; + char *name; + VALUE type, data; + + rb_scan_args(argc, argv, "11", &type, &data); + StringValue(type); + if (!NIL_P(data)) StringValue(data); + name = StringValuePtr(type); + + md = EVP_get_digestbyname(name); + if (!md) { + ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name); + } + GetDigest(self, ctx); + EVP_DigestInit_ex(ctx, md, NULL); + + if (!NIL_P(data)) return ossl_digest_update(self, data); + return self; +} + +static VALUE +ossl_digest_copy(VALUE self, VALUE other) +{ + EVP_MD_CTX *ctx1, *ctx2; + + rb_check_frozen(self); + if (self == other) return self; + + GetDigest(self, ctx1); + SafeGetDigest(other, ctx2); + + if (!EVP_MD_CTX_copy(ctx1, ctx2)) { + ossl_raise(eDigestError, NULL); + } + return self; +} + +static VALUE +ossl_digest_reset(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL); + + return self; +} + +VALUE +ossl_digest_update(VALUE self, VALUE data) +{ + EVP_MD_CTX *ctx; + + StringValue(data); + GetDigest(self, ctx); + EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len); + + return self; +} + +static void +digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len) +{ + EVP_MD_CTX final; + + if (!EVP_MD_CTX_copy(&final, ctx)) { + ossl_raise(eDigestError, NULL); + } + if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) { + EVP_MD_CTX_cleanup(&final); + ossl_raise(eDigestError, "Cannot allocate mem for digest"); + } + EVP_DigestFinal_ex(&final, *buf, buf_len); + EVP_MD_CTX_cleanup(&final); +} + +static VALUE +ossl_digest_digest(VALUE self) +{ + EVP_MD_CTX *ctx; + char *buf; + int buf_len; + VALUE digest; + + GetDigest(self, ctx); + digest_final(ctx, &buf, &buf_len); + digest = ossl_buf2str(buf, buf_len); + + return digest; +} + +static VALUE +ossl_digest_hexdigest(VALUE self) +{ + EVP_MD_CTX *ctx; + char *buf, *hexbuf; + int buf_len; + VALUE hexdigest; + + GetDigest(self, ctx); + digest_final(ctx, &buf, &buf_len); + if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { + OPENSSL_free(buf); + ossl_raise(eDigestError, "Memory alloc error"); + } + OPENSSL_free(buf); + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + + return hexdigest; +} + +static VALUE +ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data) +{ + VALUE obj = rb_class_new_instance(1, &str, klass); + + ossl_digest_update(obj, data); + + return ossl_digest_digest(obj); +} + +static VALUE +ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data) +{ + VALUE obj = rb_class_new_instance(1, &str, klass); + + ossl_digest_update(obj, data); + + return ossl_digest_hexdigest(obj); +} + +static VALUE +ossl_digest_equal(VALUE self, VALUE other) +{ + EVP_MD_CTX *ctx; + VALUE str1, str2; + + if (rb_obj_is_kind_of(other, cDigest) == Qtrue) { + str2 = ossl_digest_digest(other); + } else { + StringValue(other); + str2 = other; + } + GetDigest(self, ctx); + if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) { + str1 = ossl_digest_digest(self); + } else { + str1 = ossl_digest_hexdigest(self); + } + if (RSTRING(str1)->len == RSTRING(str2)->len + && rb_str_cmp(str1, str2) == 0) { + return Qtrue; + } + + return Qfalse; +} + +static VALUE +ossl_digest_name(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + + return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); +} + +static VALUE +ossl_digest_size(VALUE self) +{ + EVP_MD_CTX *ctx; + + GetDigest(self, ctx); + + return INT2NUM(EVP_MD_CTX_size(ctx)); +} + +/* + * INIT + */ +void +Init_ossl_digest() +{ + mDigest = rb_define_module_under(mOSSL, "Digest"); + + eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError); + + cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject); + + rb_define_alloc_func(cDigest, ossl_digest_alloc); + rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2); + rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2); + + rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); + rb_define_method(cDigest, "reset", ossl_digest_reset, 0); + + rb_define_copy_func(cDigest, ossl_digest_copy); + + rb_define_method(cDigest, "digest", ossl_digest_digest, 0); + rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0); + rb_define_alias(cDigest, "inspect", "hexdigest"); + rb_define_alias(cDigest, "to_s", "hexdigest"); + + rb_define_method(cDigest, "update", ossl_digest_update, 1); + rb_define_alias(cDigest, "<<", "update"); + + rb_define_method(cDigest, "==", ossl_digest_equal, 1); + + rb_define_method(cDigest, "name", ossl_digest_name, 0); + rb_define_method(cDigest, "size", ossl_digest_size, 0); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_digest.h b/ruby_1_8_5/ext/openssl/ossl_digest.h new file mode 100644 index 0000000000..b35bd217b3 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_digest.h @@ -0,0 +1,23 @@ +/* + * $Id: ossl_digest.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_DIGEST_H_) +#define _OSSL_DIGEST_H_ + +extern VALUE mDigest; +extern VALUE cDigest; +extern VALUE eDigestError; + +const EVP_MD *GetDigestPtr(VALUE); +VALUE ossl_digest_new(const EVP_MD *); +void Init_ossl_digest(void); + +#endif /* _OSSL_DIGEST_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_engine.c b/ruby_1_8_5/ext/openssl/ossl_engine.c new file mode 100644 index 0000000000..6cc0183c0e --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_engine.c @@ -0,0 +1,393 @@ +/* + * $Id: ossl_engine.c,v 1.4.2.6 2005/09/18 22:56:11 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2003 GOTOU Yuuzou + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#if defined(OSSL_ENGINE_ENABLED) + +#define WrapEngine(klass, obj, engine) do { \ + if (!engine) { \ + ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ + } \ + obj = Data_Wrap_Struct(klass, 0, ENGINE_free, engine); \ +} while(0) +#define GetEngine(obj, engine) do { \ + Data_Get_Struct(obj, ENGINE, engine); \ + if (!engine) { \ + ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ + } \ +} while (0) +#define SafeGetEngine(obj, engine) do { \ + OSSL_Check_Kind(obj, cEngine); \ + GetPKCS7(obj, engine); \ +} while (0) + +/* + * Classes + */ +VALUE cEngine; +VALUE eEngineError; + +/* + * Private + */ +#define OSSL_ENGINE_LOAD_IF_MATCH(x) \ +do{\ + if(!strcmp(#x, RSTRING(name)->ptr)){\ + ENGINE_load_##x();\ + return Qtrue;\ + }\ +}while(0) + +static VALUE +ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) +{ +#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES) + return Qnil; +#else + VALUE name; + + rb_scan_args(argc, argv, "01", &name); + if(NIL_P(name)){ + ENGINE_load_builtin_engines(); + return Qtrue; + } + StringValue(name); +#ifndef OPENSSL_NO_STATIC_ENGINE + OSSL_ENGINE_LOAD_IF_MATCH(dynamic); + OSSL_ENGINE_LOAD_IF_MATCH(cswift); + OSSL_ENGINE_LOAD_IF_MATCH(chil); + OSSL_ENGINE_LOAD_IF_MATCH(atalla); + OSSL_ENGINE_LOAD_IF_MATCH(nuron); + OSSL_ENGINE_LOAD_IF_MATCH(ubsec); + OSSL_ENGINE_LOAD_IF_MATCH(aep); + OSSL_ENGINE_LOAD_IF_MATCH(sureware); + OSSL_ENGINE_LOAD_IF_MATCH(4758cca); +#endif +#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO + OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto); +#endif + OSSL_ENGINE_LOAD_IF_MATCH(openssl); + rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr); + return Qnil; +#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ +} + +static VALUE +ossl_engine_s_cleanup(VALUE self) +{ +#if defined(HAVE_ENGINE_CLEANUP) + ENGINE_cleanup(); +#endif + return Qnil; +} + +static VALUE +ossl_engine_s_engines(VALUE klass) +{ + ENGINE *e; + VALUE ary, obj; + + ary = rb_ary_new(); + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){ + WrapEngine(klass, obj, e); + rb_ary_push(ary, obj); + } + + return ary; +} + +static VALUE +ossl_engine_s_by_id(VALUE klass, VALUE id) +{ + ENGINE *e; + VALUE obj; + + StringValue(id); + ossl_engine_s_load(1, &id, klass); + if(!(e = ENGINE_by_id(RSTRING(id)->ptr))) + ossl_raise(eEngineError, NULL); + WrapEngine(klass, obj, e); + if(rb_block_given_p()) rb_yield(obj); + if(!ENGINE_init(e)) + ossl_raise(eEngineError, NULL); + ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, + 0, NULL, (void(*)())ossl_pem_passwd_cb); + ERR_clear_error(); + + return obj; +} + +static VALUE +ossl_engine_s_alloc(VALUE klass) +{ + ENGINE *e; + VALUE obj; + + if (!(e = ENGINE_new())) { + ossl_raise(eEngineError, NULL); + } + WrapEngine(klass, obj, e); + + return obj; +} + +static VALUE +ossl_engine_get_id(VALUE self) +{ + ENGINE *e; + GetEngine(self, e); + return rb_str_new2(ENGINE_get_id(e)); +} + +static VALUE +ossl_engine_get_name(VALUE self) +{ + ENGINE *e; + GetEngine(self, e); + return rb_str_new2(ENGINE_get_name(e)); +} + +static VALUE +ossl_engine_finish(VALUE self) +{ + ENGINE *e; + + GetEngine(self, e); + if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL); + + return Qnil; +} + +static VALUE +ossl_engine_get_cipher(VALUE self, VALUE name) +{ +#if defined(HAVE_ENGINE_GET_CIPHER) + ENGINE *e; + const EVP_CIPHER *ciph, *tmp; + char *s; + int nid; + + s = StringValuePtr(name); + tmp = EVP_get_cipherbyname(s); + if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); + nid = EVP_CIPHER_nid(tmp); + GetEngine(self, e); + ciph = ENGINE_get_cipher(e, nid); + if(!ciph) ossl_raise(eEngineError, NULL); + + return ossl_cipher_new(ciph); +#else + rb_notimplement(); +#endif +} + +static VALUE +ossl_engine_get_digest(VALUE self, VALUE name) +{ +#if defined(HAVE_ENGINE_GET_DIGEST) + ENGINE *e; + const EVP_MD *md, *tmp; + char *s; + int nid; + + s = StringValuePtr(name); + tmp = EVP_get_digestbyname(s); + if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); + nid = EVP_MD_nid(tmp); + GetEngine(self, e); + md = ENGINE_get_digest(e, nid); + if(!md) ossl_raise(eEngineError, NULL); + + return ossl_digest_new(md); +#else + rb_notimplement(); +#endif +} + +static VALUE +ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) +{ + ENGINE *e; + EVP_PKEY *pkey; + VALUE id, data, obj; + char *sid, *sdata; + + rb_scan_args(argc, argv, "02", &id, &data); + sid = NIL_P(id) ? NULL : StringValuePtr(id); + sdata = NIL_P(data) ? NULL : StringValuePtr(data); + GetEngine(self, e); +#if OPENSSL_VERSION_NUMBER < 0x00907000L + pkey = ENGINE_load_private_key(e, sid, sdata); +#else + pkey = ENGINE_load_private_key(e, sid, NULL, sdata); +#endif + if (!pkey) ossl_raise(eEngineError, NULL); + obj = ossl_pkey_new(pkey); + OSSL_PKEY_SET_PRIVATE(obj); + + return obj; +} + +static VALUE +ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) +{ + ENGINE *e; + EVP_PKEY *pkey; + VALUE id, data; + char *sid, *sdata; + + rb_scan_args(argc, argv, "02", &id, &data); + sid = NIL_P(id) ? NULL : StringValuePtr(id); + sdata = NIL_P(data) ? NULL : StringValuePtr(data); + GetEngine(self, e); +#if OPENSSL_VERSION_NUMBER < 0x00907000L + pkey = ENGINE_load_public_key(e, sid, sdata); +#else + pkey = ENGINE_load_public_key(e, sid, NULL, sdata); +#endif + if (!pkey) ossl_raise(eEngineError, NULL); + + return ossl_pkey_new(pkey); +} + +static VALUE +ossl_engine_set_default(VALUE self, VALUE flag) +{ + ENGINE *e; + int f = NUM2INT(flag); + + GetEngine(self, e); + ENGINE_set_default(e, f); + + return Qtrue; +} + +static VALUE +ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) +{ + ENGINE *e; + VALUE cmd, val; + int ret; + + GetEngine(self, e); + rb_scan_args(argc, argv, "11", &cmd, &val); + StringValue(cmd); + if (!NIL_P(val)) StringValue(val); + ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr, + NIL_P(val) ? NULL : RSTRING(val)->ptr, 0); + if (!ret) ossl_raise(eEngineError, NULL); + + return self; +} + +static VALUE +ossl_engine_cmd_flag_to_name(int flag) +{ + switch(flag){ + case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); + case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); + case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); + case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); + default: return rb_str_new2("UNKNOWN"); + } +} + +static VALUE +ossl_engine_get_cmds(VALUE self) +{ + ENGINE *e; + const ENGINE_CMD_DEFN *defn, *p; + VALUE ary, tmp; + + GetEngine(self, e); + ary = rb_ary_new(); + if ((defn = ENGINE_get_cmd_defns(e)) != NULL){ + for (p = defn; p->cmd_num > 0; p++){ + tmp = rb_ary_new(); + rb_ary_push(tmp, rb_str_new2(p->cmd_name)); + rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); + rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); + rb_ary_push(ary, tmp); + } + } + + return ary; +} + +static VALUE +ossl_engine_inspect(VALUE self) +{ + VALUE str; + char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new2("#<"); + rb_str_cat2(str, cname); + rb_str_cat2(str, " id=\""); + rb_str_append(str, ossl_engine_get_id(self)); + rb_str_cat2(str, "\" name=\""); + rb_str_append(str, ossl_engine_get_name(self)); + rb_str_cat2(str, "\">"); + + return str; +} + +#define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x)) + +void +Init_ossl_engine() +{ + cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject); + eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError); + + rb_define_alloc_func(cEngine, ossl_engine_s_alloc); + rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1); + rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0); + rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0); + rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1); + rb_undef_method(CLASS_OF(cEngine), "new"); + + rb_define_method(cEngine, "id", ossl_engine_get_id, 0); + rb_define_method(cEngine, "name", ossl_engine_get_name, 0); + rb_define_method(cEngine, "finish", ossl_engine_finish, 0); + rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1); + rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1); + rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1); + rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1); + rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1); + rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1); + rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0); + rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0); + + DefEngineConst(METHOD_RSA); + DefEngineConst(METHOD_DSA); + DefEngineConst(METHOD_DH); + DefEngineConst(METHOD_RAND); +#ifdef ENGINE_METHOD_BN_MOD_EXP + DefEngineConst(METHOD_BN_MOD_EXP); +#endif +#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT + DefEngineConst(METHOD_BN_MOD_EXP_CRT); +#endif +#ifdef ENGINE_METHOD_CIPHERS + DefEngineConst(METHOD_CIPHERS); +#endif +#ifdef ENGINE_METHOD_DIGESTS + DefEngineConst(METHOD_DIGESTS); +#endif + DefEngineConst(METHOD_ALL); + DefEngineConst(METHOD_NONE); +} +#else +void +Init_ossl_engine() +{ +} +#endif diff --git a/ruby_1_8_5/ext/openssl/ossl_engine.h b/ruby_1_8_5/ext/openssl/ossl_engine.h new file mode 100644 index 0000000000..ccc426481a --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_engine.h @@ -0,0 +1,20 @@ +/* + * $Id: ossl_engine.h,v 1.1 2003/10/02 08:47:11 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2003 Michal Rokos + * Copyright (C) 2003 GOTOU Yuuzou + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(OSSL_ENGINE_H) +#define OSSL_ENGINE_H + +extern VALUE cEngine; +extern VALUE eEngineError; + +void Init_ossl_engine(void); + +#endif /* OSSL_ENGINE_H */ diff --git a/ruby_1_8_5/ext/openssl/ossl_hmac.c b/ruby_1_8_5/ext/openssl/ossl_hmac.c new file mode 100644 index 0000000000..cd66ab6e2c --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_hmac.c @@ -0,0 +1,220 @@ +/* + * $Id: ossl_hmac.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(OPENSSL_NO_HMAC) + +#include "ossl.h" + +#define MakeHMAC(obj, klass, ctx) \ + obj = Data_Make_Struct(klass, HMAC_CTX, 0, ossl_hmac_free, ctx) +#define GetHMAC(obj, ctx) do { \ + Data_Get_Struct(obj, HMAC_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ + } \ +} while (0) +#define SafeGetHMAC(obj, ctx) do { \ + OSSL_Check_Kind(obj, cHMAC); \ + GetHMAC(obj, ctx); \ +} while (0) + +/* + * Classes + */ +VALUE cHMAC; +VALUE eHMACError; + +/* + * Public + */ + +/* + * Private + */ +static void +ossl_hmac_free(HMAC_CTX *ctx) +{ + HMAC_CTX_cleanup(ctx); + free(ctx); +} + +static VALUE +ossl_hmac_alloc(VALUE klass) +{ + HMAC_CTX *ctx; + VALUE obj; + + MakeHMAC(obj, klass, ctx); + HMAC_CTX_init(ctx); + + return obj; +} + +static VALUE +ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) +{ + HMAC_CTX *ctx; + + StringValue(key); + GetHMAC(self, ctx); + HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len, + GetDigestPtr(digest), NULL); + + return self; +} + +static VALUE +ossl_hmac_copy(VALUE self, VALUE other) +{ + HMAC_CTX *ctx1, *ctx2; + + rb_check_frozen(self); + if (self == other) return self; + + GetHMAC(self, ctx1); + SafeGetHMAC(other, ctx2); + + if (!HMAC_CTX_copy(ctx1, ctx2)) { + ossl_raise(eHMACError, NULL); + } + return self; +} + +static VALUE +ossl_hmac_update(VALUE self, VALUE data) +{ + HMAC_CTX *ctx; + + StringValue(data); + GetHMAC(self, ctx); + HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len); + + return self; +} + +static void +hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len) +{ + HMAC_CTX final; + + if (!HMAC_CTX_copy(&final, ctx)) { + ossl_raise(eHMACError, NULL); + } + if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) { + HMAC_CTX_cleanup(&final); + OSSL_Debug("Allocating %d mem", HMAC_size(&final)); + ossl_raise(eHMACError, "Cannot allocate memory for hmac"); + } + HMAC_Final(&final, *buf, buf_len); + HMAC_CTX_cleanup(&final); +} + +static VALUE +ossl_hmac_digest(VALUE self) +{ + HMAC_CTX *ctx; + char *buf; + int buf_len; + VALUE digest; + + GetHMAC(self, ctx); + hmac_final(ctx, &buf, &buf_len); + digest = ossl_buf2str(buf, buf_len); + + return digest; +} + +static VALUE +ossl_hmac_hexdigest(VALUE self) +{ + HMAC_CTX *ctx; + char *buf, *hexbuf; + int buf_len; + VALUE hexdigest; + + GetHMAC(self, ctx); + hmac_final(ctx, &buf, &buf_len); + if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { + OPENSSL_free(buf); + ossl_raise(eHMACError, "Memory alloc error"); + } + OPENSSL_free(buf); + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + + return hexdigest; +} + +static VALUE +ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data) +{ + char *buf; + int buf_len; + + StringValue(key); + StringValue(data); + buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len, + RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len); + + return rb_str_new(buf, buf_len); +} + +static VALUE +ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data) +{ + char *buf, *hexbuf; + int buf_len; + VALUE hexdigest; + + StringValue(key); + StringValue(data); + + buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len, + RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len); + if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { + ossl_raise(eHMACError, "Cannot convert buf to hexbuf"); + } + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + + return hexdigest; +} + +/* + * INIT + */ +void +Init_ossl_hmac() +{ + eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError); + + cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject); + + rb_define_alloc_func(cHMAC, ossl_hmac_alloc); + rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3); + rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3); + + rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); + rb_define_copy_func(cHMAC, ossl_hmac_copy); + + rb_define_method(cHMAC, "update", ossl_hmac_update, 1); + rb_define_alias(cHMAC, "<<", "update"); + rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0); + rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0); + rb_define_alias(cHMAC, "inspect", "hexdigest"); + rb_define_alias(cHMAC, "to_s", "hexdigest"); +} + +#else /* NO_HMAC */ +# warning >>> OpenSSL is compiled without HMAC support <<< +void +Init_ossl_hmac() +{ + rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC."); +} +#endif /* NO_HMAC */ diff --git a/ruby_1_8_5/ext/openssl/ossl_hmac.h b/ruby_1_8_5/ext/openssl/ossl_hmac.h new file mode 100644 index 0000000000..2c8d69c177 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_hmac.h @@ -0,0 +1,19 @@ +/* + * $Id: ossl_hmac.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_HMAC_H_) +#define _OSSL_HMAC_H_ + +extern VALUE cHMAC; +extern VALUE eHMACError; + +void Init_ossl_hmac(void); + +#endif /* _OSSL_HMAC_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_ns_spki.c b/ruby_1_8_5/ext/openssl/ossl_ns_spki.c new file mode 100644 index 0000000000..bd8c59faf9 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ns_spki.c @@ -0,0 +1,256 @@ +/* + * $Id: ossl_ns_spki.c,v 1.3.2.5 2006/03/17 10:10:53 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapSPKI(klass, obj, spki) do { \ + if (!spki) { \ + ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, NETSCAPE_SPKI_free, spki); \ +} while (0) +#define GetSPKI(obj, spki) do { \ + Data_Get_Struct(obj, NETSCAPE_SPKI, spki); \ + if (!spki) { \ + ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \ + } \ +} while (0) + +/* + * Classes + */ +VALUE mNetscape; +VALUE cSPKI; +VALUE eSPKIError; + +/* + * Public functions + */ + +/* + * Private functions + */ +static VALUE +ossl_spki_alloc(VALUE klass) +{ + NETSCAPE_SPKI *spki; + VALUE obj; + + if (!(spki = NETSCAPE_SPKI_new())) { + ossl_raise(eSPKIError, NULL); + } + WrapSPKI(klass, obj, spki); + + return obj; +} + +static VALUE +ossl_spki_initialize(int argc, VALUE *argv, VALUE self) +{ + NETSCAPE_SPKI *spki; + VALUE buffer; + unsigned char *p; + + if (rb_scan_args(argc, argv, "01", &buffer) == 0) { + return self; + } + StringValue(buffer); + if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) { + p = RSTRING(buffer)->ptr; + if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) { + ossl_raise(eSPKIError, NULL); + } + } + NETSCAPE_SPKI_free(DATA_PTR(self)); + DATA_PTR(self) = spki; + + return self; +} + +static VALUE +ossl_spki_to_der(VALUE self) +{ + NETSCAPE_SPKI *spki; + VALUE str; + long len; + unsigned char *p; + + GetSPKI(self, spki); + if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0) + ossl_raise(eX509CertError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if (i2d_NETSCAPE_SPKI(spki, &p) <= 0) + ossl_raise(eX509CertError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +static VALUE +ossl_spki_to_pem(VALUE self) +{ + NETSCAPE_SPKI *spki; + char *data; + VALUE str; + + GetSPKI(self, spki); + if (!(data = NETSCAPE_SPKI_b64_encode(spki))) { + ossl_raise(eSPKIError, NULL); + } + str = ossl_buf2str(data, strlen(data)); + + return str; +} + +static VALUE +ossl_spki_print(VALUE self) +{ + NETSCAPE_SPKI *spki; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetSPKI(self, spki); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eSPKIError, NULL); + } + if (!NETSCAPE_SPKI_print(out, spki)) { + BIO_free(out); + ossl_raise(eSPKIError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +static VALUE +ossl_spki_get_public_key(VALUE self) +{ + NETSCAPE_SPKI *spki; + EVP_PKEY *pkey; + + GetSPKI(self, spki); + if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */ + ossl_raise(eSPKIError, NULL); + } + + return ossl_pkey_new(pkey); /* NO DUP - OK */ +} + +static VALUE +ossl_spki_set_public_key(VALUE self, VALUE key) +{ + NETSCAPE_SPKI *spki; + + GetSPKI(self, spki); + if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ + ossl_raise(eSPKIError, NULL); + } + + return key; +} + +static VALUE +ossl_spki_get_challenge(VALUE self) +{ + NETSCAPE_SPKI *spki; + + GetSPKI(self, spki); + if (spki->spkac->challenge->length <= 0) { + OSSL_Debug("Challenge.length <= 0?"); + return rb_str_new(0, 0); + } + + return rb_str_new(spki->spkac->challenge->data, + spki->spkac->challenge->length); +} + +static VALUE +ossl_spki_set_challenge(VALUE self, VALUE str) +{ + NETSCAPE_SPKI *spki; + + StringValue(str); + GetSPKI(self, spki); + if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr, + RSTRING(str)->len)) { + ossl_raise(eSPKIError, NULL); + } + + return str; +} + +static VALUE +ossl_spki_sign(VALUE self, VALUE key, VALUE digest) +{ + NETSCAPE_SPKI *spki; + EVP_PKEY *pkey; + const EVP_MD *md; + + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + md = GetDigestPtr(digest); + GetSPKI(self, spki); + if (!NETSCAPE_SPKI_sign(spki, pkey, md)) { + ossl_raise(eSPKIError, NULL); + } + + return self; +} + +/* + * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' + */ +static VALUE +ossl_spki_verify(VALUE self, VALUE key) +{ + NETSCAPE_SPKI *spki; + + GetSPKI(self, spki); + switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ + case 0: + return Qfalse; + case 1: + return Qtrue; + default: + ossl_raise(eSPKIError, NULL); + } + return Qnil; /* dummy */ +} + +/* + * NETSCAPE_SPKI init + */ +void +Init_ossl_ns_spki() +{ + mNetscape = rb_define_module_under(mOSSL, "Netscape"); + + eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError); + + cSPKI = rb_define_class_under(mNetscape, "SPKI", rb_cObject); + + rb_define_alloc_func(cSPKI, ossl_spki_alloc); + rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1); + + rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0); + rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0); + rb_define_alias(cSPKI, "to_s", "to_pem"); + rb_define_method(cSPKI, "to_text", ossl_spki_print, 0); + rb_define_method(cSPKI, "public_key", ossl_spki_get_public_key, 0); + rb_define_method(cSPKI, "public_key=", ossl_spki_set_public_key, 1); + rb_define_method(cSPKI, "sign", ossl_spki_sign, 2); + rb_define_method(cSPKI, "verify", ossl_spki_verify, 1); + rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0); + rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_ns_spki.h b/ruby_1_8_5/ext/openssl/ossl_ns_spki.h new file mode 100644 index 0000000000..2ca1fdcd62 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ns_spki.h @@ -0,0 +1,21 @@ +/* + * $Id: ossl_ns_spki.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_NS_SPKI_H_) +#define _OSSL_NS_SPKI_H_ + +extern VALUE mNetscape; +extern VALUE cSPKI; +extern VALUE eSPKIError; + +void Init_ossl_ns_spki(void); + +#endif /* _OSSL_NS_SPKI_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_ocsp.c b/ruby_1_8_5/ext/openssl/ossl_ocsp.c new file mode 100644 index 0000000000..f2097b967e --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ocsp.c @@ -0,0 +1,769 @@ +/* + * $Id: ossl_ocsp.c,v 1.4.2.2 2005/01/22 20:28:02 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2003 Michal Rokos + * Copyright (C) 2003 GOTOU Yuuzou + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#if defined(OSSL_OCSP_ENABLED) + +#define WrapOCSPReq(klass, obj, req) do { \ + if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ + obj = Data_Wrap_Struct(klass, 0, OCSP_REQUEST_free, req); \ +} while (0) +#define GetOCSPReq(obj, req) do { \ + Data_Get_Struct(obj, OCSP_REQUEST, req); \ + if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ +} while (0) +#define SafeGetOCSPReq(obj, req) do { \ + OSSL_Check_Kind(obj, cOCSPReq); \ + GetOCSPReq(obj, req); \ +} while (0) + +#define WrapOCSPRes(klass, obj, res) do { \ + if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ + obj = Data_Wrap_Struct(klass, 0, OCSP_RESPONSE_free, res); \ +} while (0) +#define GetOCSPRes(obj, res) do { \ + Data_Get_Struct(obj, OCSP_RESPONSE, res); \ + if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ +} while (0) +#define SafeGetOCSPRes(obj, res) do { \ + OSSL_Check_Kind(obj, cOCSPRes); \ + GetOCSPRes(obj, res); \ +} while (0) + +#define WrapOCSPBasicRes(klass, obj, res) do { \ + if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ + obj = Data_Wrap_Struct(klass, 0, OCSP_BASICRESP_free, res); \ +} while (0) +#define GetOCSPBasicRes(obj, res) do { \ + Data_Get_Struct(obj, OCSP_BASICRESP, res); \ + if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ +} while (0) +#define SafeGetOCSPBasicRes(obj, res) do { \ + OSSL_Check_Kind(obj, cOCSPBasicRes); \ + GetOCSPBasicRes(obj, res); \ +} while (0) + +#define WrapOCSPCertId(klass, obj, cid) do { \ + if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ + obj = Data_Wrap_Struct(klass, 0, OCSP_CERTID_free, cid); \ +} while (0) +#define GetOCSPCertId(obj, cid) do { \ + Data_Get_Struct(obj, OCSP_CERTID, cid); \ + if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ +} while (0) +#define SafeGetOCSPCertId(obj, cid) do { \ + OSSL_Check_Kind(obj, cOCSPCertId); \ + GetOCSPCertId(obj, cid); \ +} while (0) + +VALUE mOCSP; +VALUE eOCSPError; +VALUE cOCSPReq; +VALUE cOCSPRes; +VALUE cOCSPBasicRes; +VALUE cOCSPCertId; + +/* + * Public + */ +static VALUE +ossl_ocspcertid_new(OCSP_CERTID *cid) +{ + VALUE obj; + WrapOCSPCertId(cOCSPCertId, obj, cid); + return obj; +} + +/* + * OCSP::Resquest + */ +static VALUE +ossl_ocspreq_alloc(VALUE klass) +{ + OCSP_REQUEST *req; + VALUE obj; + + if (!(req = OCSP_REQUEST_new())) + ossl_raise(eOCSPError, NULL); + WrapOCSPReq(klass, obj, req); + + return obj; +} + +static VALUE +ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE arg; + unsigned char *p; + + rb_scan_args(argc, argv, "01", &arg); + if(!NIL_P(arg)){ + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + p = (unsigned char*)RSTRING(arg)->ptr; + if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p, + RSTRING(arg)->len)){ + ossl_raise(eOCSPError, "cannot load DER encoded request"); + } + } + + return self; +} + +static VALUE +ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) +{ + OCSP_REQUEST *req; + VALUE val; + int ret; + + rb_scan_args(argc, argv, "01", &val); + if(NIL_P(val)) { + GetOCSPReq(self, req); + ret = OCSP_request_add1_nonce(req, NULL, -1); + } + else{ + StringValue(val); + GetOCSPReq(self, req); + ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len); + } + if(!ret) ossl_raise(eOCSPError, NULL); + + return self; +} + +/* Check nonce validity in a request and response. + * Return value reflects result: + * 1: nonces present and equal. + * 2: nonces both absent. + * 3: nonce present in response only. + * 0: nonces both present and not equal. + * -1: nonce in request only. + * + * For most responders clients can check return > 0. + * If responder doesn't handle nonces return != 0 may be + * necessary. return == 0 is always an error. + */ +static VALUE +ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) +{ + OCSP_REQUEST *req; + OCSP_BASICRESP *bs; + int res; + + GetOCSPReq(self, req); + SafeGetOCSPBasicRes(basic_resp, bs); + res = OCSP_check_nonce(req, bs); + + return INT2NUM(res); +} + +static VALUE +ossl_ocspreq_add_certid(VALUE self, VALUE certid) +{ + OCSP_REQUEST *req; + OCSP_CERTID *id; + + GetOCSPReq(self, req); + GetOCSPCertId(certid, id); + if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id))) + ossl_raise(eOCSPError, NULL); + + return self; +} + +static VALUE +ossl_ocspreq_get_certid(VALUE self) +{ + OCSP_REQUEST *req; + OCSP_ONEREQ *one; + OCSP_CERTID *id; + VALUE ary, tmp; + int i, count; + + GetOCSPReq(self, req); + count = OCSP_request_onereq_count(req); + ary = (count > 0) ? rb_ary_new() : Qnil; + for(i = 0; i < count; i++){ + one = OCSP_request_onereq_get0(req, i); + if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one)))) + ossl_raise(eOCSPError, NULL); + WrapOCSPCertId(cOCSPCertId, tmp, id); + rb_ary_push(ary, tmp); + } + + return ary; +} + +static VALUE +ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) +{ + VALUE signer_cert, signer_key, certs, flags; + OCSP_REQUEST *req; + X509 *signer; + EVP_PKEY *key; + STACK_OF(X509) *x509s; + unsigned long flg; + int ret; + + rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + signer = GetX509CertPtr(signer_cert); + key = GetPrivPKeyPtr(signer_key); + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + if(NIL_P(certs)){ + x509s = sk_X509_new_null(); + flags |= OCSP_NOCERTS; + } + else x509s = ossl_x509_ary2sk(certs); + GetOCSPReq(self, req); + ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg); + sk_X509_pop_free(x509s, X509_free); + if(!ret) ossl_raise(eOCSPError, NULL); + + return self; +} + +static VALUE +ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE certs, store, flags; + OCSP_REQUEST *req; + STACK_OF(X509) *x509s; + X509_STORE *x509st; + int flg, result; + + rb_scan_args(argc, argv, "21", &certs, &store, &flags); + x509st = GetX509StorePtr(store); + flg = NIL_P(flags) ? 0 : INT2NUM(flags); + x509s = ossl_x509_ary2sk(certs); + GetOCSPReq(self, req); + result = OCSP_request_verify(req, x509s, x509st, flg); + sk_X509_pop_free(x509s, X509_free); + if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); + + return result ? Qtrue : Qfalse; +} + +static VALUE +ossl_ocspreq_to_der(VALUE self) +{ + OCSP_REQUEST *req; + VALUE str; + unsigned char *p; + long len; + + GetOCSPReq(self, req); + if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_OCSP_REQUEST(req, &p) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * OCSP::Response + */ +static VALUE +ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp) +{ + OCSP_BASICRESP *bs; + OCSP_RESPONSE *res; + VALUE obj; + int st = NUM2INT(status); + + if(NIL_P(basic_resp)) bs = NULL; + else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */ + if(!(res = OCSP_response_create(st, bs))) + ossl_raise(eOCSPError, NULL); + WrapOCSPRes(klass, obj, res); + + return obj; +} + +static VALUE +ossl_ocspres_alloc(VALUE klass) +{ + OCSP_RESPONSE *res; + VALUE obj; + + if(!(res = OCSP_RESPONSE_new())) + ossl_raise(eOCSPError, NULL); + WrapOCSPRes(klass, obj, res); + + return obj; +} + +static VALUE +ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE arg; + unsigned char *p; + + rb_scan_args(argc, argv, "01", &arg); + if(!NIL_P(arg)){ + arg = ossl_to_der_if_possible(arg); + StringValue(arg); + p = RSTRING(arg)->ptr; + if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p, + RSTRING(arg)->len)){ + ossl_raise(eOCSPError, "cannot load DER encoded response"); + } + } + + return self; +} + +static VALUE +ossl_ocspres_status(VALUE self) +{ + OCSP_RESPONSE *res; + int st; + + GetOCSPRes(self, res); + st = OCSP_response_status(res); + + return INT2NUM(st); +} + +static VALUE +ossl_ocspres_status_string(VALUE self) +{ + OCSP_RESPONSE *res; + int st; + + GetOCSPRes(self, res); + st = OCSP_response_status(res); + + return rb_str_new2(OCSP_response_status_str(st)); +} + +static VALUE +ossl_ocspres_get_basic(VALUE self) +{ + OCSP_RESPONSE *res; + OCSP_BASICRESP *bs; + VALUE ret; + + GetOCSPRes(self, res); + if(!(bs = OCSP_response_get1_basic(res))) + return Qnil; + WrapOCSPBasicRes(cOCSPBasicRes, ret, bs); + + return ret; +} + +static VALUE +ossl_ocspres_to_der(VALUE self) +{ + OCSP_RESPONSE *res; + VALUE str; + long len; + unsigned char *p; + + GetOCSPRes(self, res); + if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_OCSP_RESPONSE(res, NULL) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * OCSP::BasicResponse + */ +static VALUE +ossl_ocspbres_alloc(VALUE klass) +{ + OCSP_BASICRESP *bs; + VALUE obj; + + if(!(bs = OCSP_BASICRESP_new())) + ossl_raise(eOCSPError, NULL); + WrapOCSPBasicRes(klass, obj, bs); + + return obj; +} + +static VALUE +ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self) +{ + return self; +} + +static VALUE +ossl_ocspbres_copy_nonce(VALUE self, VALUE request) +{ + OCSP_BASICRESP *bs; + OCSP_REQUEST *req; + int ret; + + GetOCSPBasicRes(self, bs); + SafeGetOCSPReq(request, req); + ret = OCSP_copy_nonce(bs, req); + + return INT2NUM(ret); +} + +static VALUE +ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self) +{ + OCSP_BASICRESP *bs; + VALUE val; + int ret; + + rb_scan_args(argc, argv, "01", &val); + if(NIL_P(val)) { + GetOCSPBasicRes(self, bs); + ret = OCSP_basic_add1_nonce(bs, NULL, -1); + } + else{ + StringValue(val); + GetOCSPBasicRes(self, bs); + ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len); + } + if(!ret) ossl_raise(eOCSPError, NULL); + + return self; +} + +static VALUE +ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, + VALUE reason, VALUE revtime, + VALUE thisupd, VALUE nextupd, VALUE ext) +{ + OCSP_BASICRESP *bs; + OCSP_SINGLERESP *single; + OCSP_CERTID *id; + int st, rsn; + ASN1_TIME *ths, *nxt, *rev; + int error, i, rstatus = 0; + VALUE tmp; + + st = NUM2INT(status); + rsn = NIL_P(status) ? 0 : NUM2INT(reason); + if(!NIL_P(ext)){ + /* All ary's members should be X509Extension */ + Check_Type(ext, T_ARRAY); + for (i = 0; i < RARRAY(ext)->len; i++) + OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext); + } + + error = 0; + ths = nxt = rev = NULL; + if(!NIL_P(revtime)){ + tmp = rb_protect(rb_Integer, revtime, &rstatus); + if(rstatus) goto err; + rev = X509_gmtime_adj(NULL, NUM2INT(tmp)); + } + tmp = rb_protect(rb_Integer, thisupd, &rstatus); + if(rstatus) goto err; + ths = X509_gmtime_adj(NULL, NUM2INT(tmp)); + tmp = rb_protect(rb_Integer, nextupd, &rstatus); + if(rstatus) goto err; + nxt = X509_gmtime_adj(NULL, NUM2INT(tmp)); + + GetOCSPBasicRes(self, bs); + SafeGetOCSPCertId(cid, id); + if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){ + error = 1; + goto err; + } + + if(!NIL_P(ext)){ + X509_EXTENSION *x509ext; + sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free); + single->singleExtensions = NULL; + for(i = 0; i < RARRAY(ext)->len; i++){ + x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]); + if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){ + X509_EXTENSION_free(x509ext); + error = 1; + goto err; + } + X509_EXTENSION_free(x509ext); + } + } + + err: + ASN1_TIME_free(ths); + ASN1_TIME_free(nxt); + ASN1_TIME_free(rev); + if(error) ossl_raise(eOCSPError, NULL); + if(rstatus) rb_jump_tag(rstatus); + + return self; +} + +static VALUE +ossl_ocspbres_get_status(VALUE self) +{ + OCSP_BASICRESP *bs; + OCSP_SINGLERESP *single; + OCSP_CERTID *cid; + ASN1_TIME *revtime, *thisupd, *nextupd; + int status, reason; + X509_EXTENSION *x509ext; + VALUE ret, ary, ext; + int count, ext_count, i, j; + + GetOCSPBasicRes(self, bs); + ret = rb_ary_new(); + count = OCSP_resp_count(bs); + for(i = 0; i < count; i++){ + single = OCSP_resp_get0(bs, i); + if(!single) continue; + + revtime = thisupd = nextupd = NULL; + status = OCSP_single_get0_status(single, &reason, &revtime, + &thisupd, &nextupd); + if(status < 0) continue; + if(!(cid = OCSP_CERTID_dup(single->certId))) + ossl_raise(eOCSPError, NULL); + ary = rb_ary_new(); + rb_ary_push(ary, ossl_ocspcertid_new(cid)); + rb_ary_push(ary, INT2NUM(status)); + rb_ary_push(ary, INT2NUM(reason)); + rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); + rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); + rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); + ext = rb_ary_new(); + ext_count = OCSP_SINGLERESP_get_ext_count(single); + for(j = 0; j < ext_count; j++){ + x509ext = OCSP_SINGLERESP_get_ext(single, j); + rb_ary_push(ext, ossl_x509ext_new(x509ext)); + } + rb_ary_push(ary, ext); + rb_ary_push(ret, ary); + } + + return ret; +} + +static VALUE +ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) +{ + VALUE signer_cert, signer_key, certs, flags; + OCSP_BASICRESP *bs; + X509 *signer; + EVP_PKEY *key; + STACK_OF(X509) *x509s; + unsigned long flg; + int ret; + + rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + signer = GetX509CertPtr(signer_cert); + key = GetPrivPKeyPtr(signer_key); + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + if(NIL_P(certs)){ + x509s = sk_X509_new_null(); + flg |= OCSP_NOCERTS; + } + else{ + x509s = ossl_x509_ary2sk(certs); + } + GetOCSPBasicRes(self, bs); + ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg); + sk_X509_pop_free(x509s, X509_free); + if(!ret) ossl_raise(eOCSPError, NULL); + + return self; +} + +static VALUE +ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE certs, store, flags; + OCSP_BASICRESP *bs; + STACK_OF(X509) *x509s; + X509_STORE *x509st; + int flg, result; + + rb_scan_args(argc, argv, "21", &certs, &store, &flags); + x509st = GetX509StorePtr(store); + flg = NIL_P(flags) ? 0 : INT2NUM(flags); + x509s = ossl_x509_ary2sk(certs); + GetOCSPBasicRes(self, bs); + result = OCSP_basic_verify(bs, x509s, x509st, flg); + sk_X509_pop_free(x509s, X509_free); + if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL)); + + return result ? Qtrue : Qfalse; +} + +/* + * OCSP::CertificateId + */ +static VALUE +ossl_ocspcid_alloc(VALUE klass) +{ + OCSP_CERTID *id; + VALUE obj; + + if(!(id = OCSP_CERTID_new())) + ossl_raise(eOCSPError, NULL); + WrapOCSPCertId(klass, obj, id); + + return obj; +} + +static VALUE +ossl_ocspcid_initialize(VALUE self, VALUE subject, VALUE issuer) +{ + OCSP_CERTID *id, *newid; + X509 *x509s, *x509i; + + x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ + x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ + if(!(newid = OCSP_cert_to_id(NULL, x509s, x509i))) + ossl_raise(eOCSPError, NULL); + GetOCSPCertId(self, id); + OCSP_CERTID_free(id); + RDATA(self)->data = newid; + + return self; +} + +static VALUE +ossl_ocspcid_cmp(VALUE self, VALUE other) +{ + OCSP_CERTID *id, *id2; + int result; + + GetOCSPCertId(self, id); + SafeGetOCSPCertId(other, id2); + result = OCSP_id_cmp(id, id2); + + return (result == 0) ? Qtrue : Qfalse; +} + +static VALUE +ossl_ocspcid_cmp_issuer(VALUE self, VALUE other) +{ + OCSP_CERTID *id, *id2; + int result; + + GetOCSPCertId(self, id); + SafeGetOCSPCertId(other, id2); + result = OCSP_id_issuer_cmp(id, id2); + + return (result == 0) ? Qtrue : Qfalse; +} + +static VALUE +ossl_ocspcid_get_serial(VALUE self) +{ + OCSP_CERTID *id; + + GetOCSPCertId(self, id); + + return asn1integer_to_num(id->serialNumber); +} + +void +Init_ossl_ocsp() +{ + mOCSP = rb_define_module_under(mOSSL, "OCSP"); + + eOCSPError = rb_define_class_under(mOCSP, "OCSPError", rb_cObject); + + cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject); + rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc); + rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1); + rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1); + rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1); + rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1); + rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0); + rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1); + rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1); + rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0); + + cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject); + rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2); + rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc); + rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1); + rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0); + rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0); + rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0); + rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0); + + cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject); + rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc); + rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1); + rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1); + rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1); + rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7); + rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0); + rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1); + rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1); + + cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject); + rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc); + rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, 2); + rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1); + rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1); + rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0); + +#define DefOCSPConst(x) rb_define_const(mOCSP, #x, INT2NUM(OCSP_##x)) + + DefOCSPConst(RESPONSE_STATUS_SUCCESSFUL); + DefOCSPConst(RESPONSE_STATUS_MALFORMEDREQUEST); + DefOCSPConst(RESPONSE_STATUS_INTERNALERROR); + DefOCSPConst(RESPONSE_STATUS_TRYLATER); + DefOCSPConst(RESPONSE_STATUS_SIGREQUIRED); + DefOCSPConst(RESPONSE_STATUS_UNAUTHORIZED); + + DefOCSPConst(REVOKED_STATUS_NOSTATUS); + DefOCSPConst(REVOKED_STATUS_UNSPECIFIED); + DefOCSPConst(REVOKED_STATUS_KEYCOMPROMISE); + DefOCSPConst(REVOKED_STATUS_CACOMPROMISE); + DefOCSPConst(REVOKED_STATUS_AFFILIATIONCHANGED); + DefOCSPConst(REVOKED_STATUS_SUPERSEDED); + DefOCSPConst(REVOKED_STATUS_CESSATIONOFOPERATION); + DefOCSPConst(REVOKED_STATUS_CERTIFICATEHOLD); + DefOCSPConst(REVOKED_STATUS_REMOVEFROMCRL); + + DefOCSPConst(NOCERTS); + DefOCSPConst(NOINTERN); + DefOCSPConst(NOSIGS); + DefOCSPConst(NOCHAIN); + DefOCSPConst(NOVERIFY); + DefOCSPConst(NOEXPLICIT); + DefOCSPConst(NOCASIGN); + DefOCSPConst(NODELEGATED); + DefOCSPConst(NOCHECKS); + DefOCSPConst(TRUSTOTHER); + DefOCSPConst(RESPID_KEY); + DefOCSPConst(NOTIME); + +#define DefOCSPVConst(x) rb_define_const(mOCSP, "V_" #x, INT2NUM(V_OCSP_##x)) + + DefOCSPVConst(CERTSTATUS_GOOD); + DefOCSPVConst(CERTSTATUS_REVOKED); + DefOCSPVConst(CERTSTATUS_UNKNOWN); + DefOCSPVConst(RESPID_NAME); + DefOCSPVConst(RESPID_KEY); +} + +#else /* ! OSSL_OCSP_ENABLED */ +void +Init_ossl_ocsp() +{ +} +#endif diff --git a/ruby_1_8_5/ext/openssl/ossl_ocsp.h b/ruby_1_8_5/ext/openssl/ossl_ocsp.h new file mode 100644 index 0000000000..244fbb2a74 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ocsp.h @@ -0,0 +1,24 @@ +/* + * $Id: ossl_ocsp.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2003 Michal Rokos + * Copyright (C) 2003 GOTOU Yuuzou + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_OCSP_H_) +#define _OSSL_OCSP_H_ + +#if defined(OSSL_OCSP_ENABLED) +extern VALUE mOCSP; +extern VALUE cOPCSReq; +extern VALUE cOPCSRes; +extern VALUE cOPCSBasicRes; +#endif + +void Init_ossl_ocsp(void); + +#endif /* _OSSL_OCSP_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs12.c b/ruby_1_8_5/ext/openssl/ossl_pkcs12.c new file mode 100644 index 0000000000..e4b334c67e --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkcs12.c @@ -0,0 +1,154 @@ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + * $Id: ossl_pkcs12.c,v 1.2 2003/12/15 00:30:12 usa Exp $ + */ +#include "ossl.h" + +#define WrapPKCS12(klass, obj, p12) do { \ + if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ + obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \ +} while (0) + +#define GetPKCS12(obj, p12) do { \ + Data_Get_Struct(obj, PKCS12, p12); \ + if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ +} while (0) + +#define SafeGetPKCS12(obj, p12) do { \ + OSSL_Check_Kind(obj, cPKCS12); \ + GetPKCS12(obj, p12); \ +} while (0) + +#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v)) +#define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v)) +#define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v)) +#define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key") +#define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate") +#define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs") + +/* + * Classes + */ +VALUE mPKCS12; +VALUE cPKCS12; +VALUE ePKCS12Error; + +/* + * Private + */ +static VALUE +ossl_pkcs12_s_allocate(VALUE klass) +{ + PKCS12 *p12; + VALUE obj; + + if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL); + WrapPKCS12(klass, obj, p12); + + return obj; +} + +static VALUE +ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) +{ + VALUE pass, name, pkey, cert, ca; + VALUE obj; + char *passphrase, *friendlyname; + EVP_PKEY *key; + X509 *x509; + STACK_OF(X509) *x509s; + PKCS12 *p12; + + rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca); + passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); + friendlyname = NIL_P(name) ? NULL : StringValuePtr(name); + key = GetPKeyPtr(pkey); + x509 = GetX509CertPtr(cert); + x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); + p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s, + 0, 0, 0, 0, 0); + sk_X509_pop_free(x509s, X509_free); + if(!p12) ossl_raise(ePKCS12Error, NULL); + WrapPKCS12(cPKCS12, obj, p12); + + return obj; +} + +static VALUE +ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) +{ + BIO *in; + VALUE arg, pass, pkey, cert, ca; + char *passphrase; + EVP_PKEY *key; + X509 *x509; + STACK_OF(X509) *x509s = NULL; + int st = 0; + + if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; + passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); + in = ossl_obj2bio(arg); + d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self)); + BIO_free(in); + + pkey = cert = ca = Qnil; + if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s)) + ossl_raise(ePKCS12Error, NULL); + pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key, + &st); /* NO DUP */ + if(st) goto err; + cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st); + if(st) goto err; + if(x509s){ + ca = + rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st); + if(st) goto err; + } + + err: + X509_free(x509); + sk_X509_pop_free(x509s, X509_free); + ossl_pkcs12_set_key(self, pkey); + ossl_pkcs12_set_cert(self, cert); + ossl_pkcs12_set_ca_certs(self, ca); + if(st) rb_jump_tag(st); + + return self; +} + +static VALUE +ossl_pkcs12_to_der(VALUE self) +{ + PKCS12 *p12; + VALUE str; + long len; + unsigned char *p; + + GetPKCS12(self, p12); + if((len = i2d_PKCS12(p12, NULL)) <= 0) + ossl_raise(ePKCS12Error, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_PKCS12(p12, &p) <= 0) + ossl_raise(ePKCS12Error, NULL); + ossl_str_adjust(str, p); + + return str; +} + +void +Init_ossl_pkcs12() +{ + mPKCS12 = rb_define_module_under(mOSSL, "PKCS12"); + cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject); + ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError); + rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1); + + rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate); + rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse); + rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse); + rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse); + rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1); + rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs12.h b/ruby_1_8_5/ext/openssl/ossl_pkcs12.h new file mode 100644 index 0000000000..95b29de9b5 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkcs12.h @@ -0,0 +1,16 @@ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + * $Id: ossl_pkcs12.h,v 1.1.2.1 2005/06/19 16:29:17 gotoyuzo Exp $ + */ +#if !defined(_OSSL_PKCS12_H_) +#define _OSSL_PKCS12_H_ + +extern VALUE mPKCS12; +extern VALUE cPKCS12; +extern VALUE ePKCS12Error; + +void Init_ossl_pkcs12(void); + +#endif /* _OSSL_PKCS12_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs5.h b/ruby_1_8_5/ext/openssl/ossl_pkcs5.h new file mode 100644 index 0000000000..a3b132bc50 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkcs5.h @@ -0,0 +1,6 @@ +#if !defined(_OSSL_PKCS5_H_) +#define _OSSL_PKCS5_H_ + +void Init_ossl_pkcs5(void); + +#endif /* _OSSL_PKCS5_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs7.c b/ruby_1_8_5/ext/openssl/ossl_pkcs7.c new file mode 100644 index 0000000000..0fa85299aa --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkcs7.c @@ -0,0 +1,993 @@ +/* + * $Id: ossl_pkcs7.c,v 1.5.2.3 2005/09/10 01:11:15 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapPKCS7(klass, obj, pkcs7) do { \ + if (!pkcs7) { \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + } \ + obj = Data_Wrap_Struct(klass, 0, PKCS7_free, pkcs7); \ +} while (0) +#define GetPKCS7(obj, pkcs7) do { \ + Data_Get_Struct(obj, PKCS7, pkcs7); \ + if (!pkcs7) { \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + } \ +} while (0) +#define SafeGetPKCS7(obj, pkcs7) do { \ + OSSL_Check_Kind(obj, cPKCS7); \ + GetPKCS7(obj, pkcs7); \ +} while (0) + +#define WrapPKCS7si(klass, obj, p7si) do { \ + if (!p7si) { \ + ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ + } \ + obj = Data_Wrap_Struct(klass, 0, PKCS7_SIGNER_INFO_free, p7si); \ +} while (0) +#define GetPKCS7si(obj, p7si) do { \ + Data_Get_Struct(obj, PKCS7_SIGNER_INFO, p7si); \ + if (!p7si) { \ + ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ + } \ +} while (0) +#define SafeGetPKCS7si(obj, p7si) do { \ + OSSL_Check_Kind(obj, cPKCS7Signer); \ + GetPKCS7si(obj, p7si); \ +} while (0) + +#define WrapPKCS7ri(klass, obj, p7ri) do { \ + if (!p7ri) { \ + ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ + } \ + obj = Data_Wrap_Struct(klass, 0, PKCS7_RECIP_INFO_free, p7ri); \ +} while (0) +#define GetPKCS7ri(obj, p7ri) do { \ + Data_Get_Struct(obj, PKCS7_RECIP_INFO, p7ri); \ + if (!p7ri) { \ + ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ + } \ +} while (0) +#define SafeGetPKCS7ri(obj, p7ri) do { \ + OSSL_Check_Kind(obj, cPKCS7Recipient); \ + GetPKCS7ri(obj, p7ri); \ +} while (0) + +#define numberof(ary) (sizeof(ary)/sizeof(ary[0])) + +#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v)) +#define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data") +#define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v)) +#define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string") + +/* + * Classes + */ +VALUE mPKCS7; +VALUE cPKCS7; +VALUE cPKCS7Signer; +VALUE cPKCS7Recipient; +VALUE ePKCS7Error; + +/* + * Public + * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) + */ +static VALUE +ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) +{ + PKCS7_SIGNER_INFO *pkcs7; + VALUE obj; + + pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); + if (!pkcs7) ossl_raise(ePKCS7Error, NULL); + WrapPKCS7si(cPKCS7Signer, obj, pkcs7); + + return obj; +} + +static PKCS7_SIGNER_INFO * +DupPKCS7SignerPtr(VALUE obj) +{ + PKCS7_SIGNER_INFO *p7si, *pkcs7; + + SafeGetPKCS7si(obj, p7si); + if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) { + ossl_raise(ePKCS7Error, NULL); + } + + return pkcs7; +} + +static VALUE +ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) +{ + PKCS7_RECIP_INFO *pkcs7; + VALUE obj; + + pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); + if (!pkcs7) ossl_raise(ePKCS7Error, NULL); + WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7); + + return obj; +} + +static PKCS7_RECIP_INFO * +DupPKCS7RecipientPtr(VALUE obj) +{ + PKCS7_RECIP_INFO *p7ri, *pkcs7; + + SafeGetPKCS7ri(obj, p7ri); + if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) { + ossl_raise(ePKCS7Error, NULL); + } + + return pkcs7; +} + +/* + * Private + */ +static VALUE +ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) +{ + BIO *in, *out; + PKCS7 *pkcs7; + VALUE ret, data; + + in = ossl_obj2bio(arg); + out = NULL; + pkcs7 = SMIME_read_PKCS7(in, &out); + BIO_free(in); + if(!pkcs7) ossl_raise(ePKCS7Error, NULL); + data = out ? ossl_membio2str(out) : Qnil; + WrapPKCS7(cPKCS7, ret, pkcs7); + ossl_pkcs7_set_data(ret, data); + ossl_pkcs7_set_err_string(ret, Qnil); + + return ret; +} + +static VALUE +ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) +{ + VALUE pkcs7, data, flags; + BIO *out, *in; + PKCS7 *p7; + VALUE str; + int flg; + + rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7); + SafeGetPKCS7(pkcs7, p7); + if(!NIL_P(data) && PKCS7_is_detached(p7)) + flg |= PKCS7_DETACHED; + in = NIL_P(data) ? NULL : ossl_obj2bio(data); + if(!(out = BIO_new(BIO_s_mem()))){ + BIO_free(in); + ossl_raise(ePKCS7Error, NULL); + } + if(!SMIME_write_PKCS7(out, p7, in, flg)){ + BIO_free(out); + BIO_free(in); + ossl_raise(ePKCS7Error, NULL); + } + BIO_free(in); + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) +{ + VALUE cert, key, data, certs, flags; + X509 *x509; + EVP_PKEY *pkey; + BIO *in; + STACK_OF(X509) *x509s; + int flg, status = 0; + PKCS7 *pkcs7; + VALUE ret; + + rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags); + x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + in = ossl_obj2bio(data); + if(NIL_P(certs)) x509s = NULL; + else{ + x509s = ossl_protect_x509_ary2sk(certs, &status); + if(status){ + BIO_free(in); + rb_jump_tag(status); + } + } + if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){ + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); + } + WrapPKCS7(cPKCS7, ret, pkcs7); + ossl_pkcs7_set_data(ret, data); + ossl_pkcs7_set_err_string(ret, Qnil); + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + + return ret; +} + +static VALUE +ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) +{ + VALUE certs, data, cipher, flags; + STACK_OF(X509) *x509s; + BIO *in; + const EVP_CIPHER *ciph; + int flg, status = 0; + VALUE ret; + PKCS7 *p7; + + rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags); + if(NIL_P(cipher)){ +#if !defined(OPENSSL_NO_RC2) + ciph = EVP_rc2_40_cbc(); +#elif !defined(OPENSSL_NO_DES) + ciph = EVP_des_ede3_cbc(); +#elif !defined(OPENSSL_NO_RC2) + ciph = EVP_rc2_40_cbc(); +#elif !defined(OPENSSL_NO_AES) + ciph = EVP_EVP_aes_128_cbc(); +#else + ossl_raise(ePKCS7Error, "Must specify cipher"); +#endif + + } + else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + in = ossl_obj2bio(data); + x509s = ossl_protect_x509_ary2sk(certs, &status); + if(status){ + BIO_free(in); + rb_jump_tag(status); + } + if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){ + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); + } + BIO_free(in); + WrapPKCS7(cPKCS7, ret, p7); + ossl_pkcs7_set_data(ret, data); + sk_X509_pop_free(x509s, X509_free); + + return ret; +} + +static VALUE +ossl_pkcs7_alloc(VALUE klass) +{ + PKCS7 *pkcs7; + VALUE obj; + + if (!(pkcs7 = PKCS7_new())) { + ossl_raise(ePKCS7Error, NULL); + } + WrapPKCS7(klass, obj, pkcs7); + + return obj; +} + +static VALUE +ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) +{ + PKCS7 *p7; + BIO *in; + VALUE arg; + + if(rb_scan_args(argc, argv, "01", &arg) == 0) + return self; + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL); + if (!p7) { + BIO_reset(in); + p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self)); + } + BIO_free(in); + ossl_pkcs7_set_data(self, Qnil); + ossl_pkcs7_set_err_string(self, Qnil); + + return self; +} + +static VALUE +ossl_pkcs7_copy(VALUE self, VALUE other) +{ + PKCS7 *a, *b, *pkcs7; + + rb_check_frozen(self); + if (self == other) return self; + + GetPKCS7(self, a); + SafeGetPKCS7(other, b); + + pkcs7 = PKCS7_dup(b); + if (!pkcs7) { + ossl_raise(ePKCS7Error, NULL); + } + DATA_PTR(self) = pkcs7; + PKCS7_free(a); + + return self; +} + +static int +ossl_pkcs7_sym2typeid(VALUE sym) +{ + int i, ret = Qnil; + char *s; + + static struct { + const char *name; + int nid; + } p7_type_tab[] = { + { "signed", NID_pkcs7_signed }, + { "data", NID_pkcs7_data }, + { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped }, + { "enveloped", NID_pkcs7_enveloped }, + { "encrypted", NID_pkcs7_encrypted }, + { "digest", NID_pkcs7_digest }, + { NULL, 0 }, + }; + + if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym)); + else s = StringValuePtr(sym); + for(i = 0; i < numberof(p7_type_tab); i++){ + if(p7_type_tab[i].name == NULL) + ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); + if(strcmp(p7_type_tab[i].name, s) == 0){ + ret = p7_type_tab[i].nid; + break; + } + } + + return ret; +} + +static VALUE +ossl_pkcs7_set_type(VALUE self, VALUE type) +{ + PKCS7 *p7; + + GetPKCS7(self, p7); + if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type))) + ossl_raise(ePKCS7Error, NULL); + + return type; +} + +static VALUE +ossl_pkcs7_get_type(VALUE self) +{ + PKCS7 *p7; + + GetPKCS7(self, p7); + if(PKCS7_type_is_signed(p7)) + return ID2SYM(rb_intern("signed")); + if(PKCS7_type_is_encrypted(p7)) + return ID2SYM(rb_intern("encrypted")); + if(PKCS7_type_is_enveloped(p7)) + return ID2SYM(rb_intern("enveloped")); + if(PKCS7_type_is_signedAndEnveloped(p7)) + return ID2SYM(rb_intern("signedAndEnveloped")); + if(PKCS7_type_is_data(p7)) + return ID2SYM(rb_intern("data")); + return Qnil; +} + +static VALUE +ossl_pkcs7_set_detached(VALUE self, VALUE flag) +{ + PKCS7 *p7; + + GetPKCS7(self, p7); + if(flag != Qtrue && flag != Qfalse) + ossl_raise(ePKCS7Error, "must specify a boolean"); + if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) + ossl_raise(ePKCS7Error, NULL); + + return flag; +} + +static VALUE +ossl_pkcs7_get_detached(VALUE self) +{ + PKCS7 *p7; + GetPKCS7(self, p7); + return PKCS7_get_detached(p7) ? Qtrue : Qfalse; +} + +static VALUE +ossl_pkcs7_detached_p(VALUE self) +{ + PKCS7 *p7; + GetPKCS7(self, p7); + return PKCS7_is_detached(p7) ? Qtrue : Qfalse; +} + +static VALUE +ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) +{ + PKCS7 *pkcs7; + + GetPKCS7(self, pkcs7); + if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { + ossl_raise(ePKCS7Error, NULL); + } + + return cipher; +} + +static VALUE +ossl_pkcs7_add_signer(VALUE self, VALUE signer) +{ + PKCS7 *pkcs7; + PKCS7_SIGNER_INFO *p7si; + + p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ + GetPKCS7(self, pkcs7); + if (!PKCS7_add_signer(pkcs7, p7si)) { + PKCS7_SIGNER_INFO_free(p7si); + ossl_raise(ePKCS7Error, "Could not add signer."); + } + if (PKCS7_type_is_signed(pkcs7)){ + PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, + V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); + } + + return self; +} + +static VALUE +ossl_pkcs7_get_signer(VALUE self) +{ + PKCS7 *pkcs7; + STACK_OF(PKCS7_SIGNER_INFO) *sk; + PKCS7_SIGNER_INFO *si; + int num, i; + VALUE ary; + + GetPKCS7(self, pkcs7); + if (!(sk = PKCS7_get_signer_info(pkcs7))) { + OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); + return rb_ary_new(); + } + if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { + ossl_raise(ePKCS7Error, "Negative number of signers!"); + } + ary = rb_ary_new2(num); + for (i=0; id.enveloped->recipientinfo; + else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) + sk = pkcs7->d.signed_and_enveloped->recipientinfo; + else sk = NULL; + if (!sk) return rb_ary_new(); + if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { + ossl_raise(ePKCS7Error, "Negative number of recipient!"); + } + ary = rb_ary_new2(num); + for (i=0; itype); + switch(i){ + case NID_pkcs7_signed: + certs = pkcs7->d.sign->cert; + crls = pkcs7->d.sign->crl; + break; + case NID_pkcs7_signedAndEnveloped: + certs = pkcs7->d.signed_and_enveloped->cert; + crls = pkcs7->d.signed_and_enveloped->crl; + break; + default: + certs = crls = NULL; + } + + return want_certs ? certs : crls; +} + +static VALUE +ossl_pkcs7_set_certs_i(VALUE i, VALUE arg) +{ + return ossl_pkcs7_add_certificate(arg, i); +} + +static VALUE +ossl_pkcs7_set_certificates(VALUE self, VALUE ary) +{ + STACK_OF(X509) *certs; + X509 *cert; + + certs = pkcs7_get_certs_or_crls(self, 1); + while((cert = sk_X509_pop(certs))) X509_free(cert); + rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self); + + return ary; +} + +static VALUE +ossl_pkcs7_get_certificates(VALUE self) +{ + return ossl_x509_sk2ary(pkcs7_get_certs_or_crls(self, 1)); +} + +static VALUE +ossl_pkcs7_add_crl(VALUE self, VALUE crl) +{ + PKCS7 *pkcs7; + X509_CRL *x509crl; + + GetPKCS7(self, pkcs7); /* NO DUP needed! */ + x509crl = GetX509CRLPtr(crl); + if (!PKCS7_add_crl(pkcs7, x509crl)) { + ossl_raise(ePKCS7Error, NULL); + } + + return self; +} + +static VALUE +ossl_pkcs7_set_crls_i(VALUE i, VALUE arg) +{ + return ossl_pkcs7_add_crl(arg, i); +} + +static VALUE +ossl_pkcs7_set_crls(VALUE self, VALUE ary) +{ + STACK_OF(X509_CRL) *crls; + X509_CRL *crl; + + crls = pkcs7_get_certs_or_crls(self, 0); + while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl); + rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self); + + return ary; +} + +static VALUE +ossl_pkcs7_get_crls(VALUE self) +{ + return ossl_x509crl_sk2ary(pkcs7_get_certs_or_crls(self, 0)); +} + +static VALUE +ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE certs, store, indata, flags; + STACK_OF(X509) *x509s; + X509_STORE *x509st; + int flg, ok, status = 0; + BIO *in, *out; + PKCS7 *p7; + VALUE data; + const char *msg; + + rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags); + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); + in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); + if(NIL_P(certs)) x509s = NULL; + else{ + x509s = ossl_protect_x509_ary2sk(certs, &status); + if(status){ + BIO_free(in); + rb_jump_tag(status); + } + } + x509st = GetX509StorePtr(store); + GetPKCS7(self, p7); + if(!(out = BIO_new(BIO_s_mem()))){ + BIO_free(in); + sk_X509_pop_free(x509s, X509_free); + ossl_raise(ePKCS7Error, NULL); + } + ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); + BIO_free(in); + msg = ERR_reason_error_string(ERR_get_error()); + ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); + data = ossl_membio2str(out); + ossl_pkcs7_set_data(self, data); + sk_X509_pop_free(x509s, X509_free); + + return (ok == 1) ? Qtrue : Qfalse; +} + +static VALUE +ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) +{ + VALUE pkey, cert, flags; + EVP_PKEY *key; + X509 *x509; + int flg; + PKCS7 *p7; + BIO *out; + VALUE str; + + rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); + key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ + x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ + flg = NIL_P(flags) ? 0 : NUM2INT(flags); + GetPKCS7(self, p7); + if(!(out = BIO_new(BIO_s_mem()))) + ossl_raise(ePKCS7Error, NULL); + if(!PKCS7_decrypt(p7, key, x509, out, flg)){ + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); + } + str = ossl_membio2str(out); /* out will be free */ + + return str; +} + +static VALUE +ossl_pkcs7_add_data(VALUE self, VALUE data) +{ + PKCS7 *pkcs7; + BIO *out, *in; + char buf[4096]; + int len; + + in = ossl_obj2bio(data); + GetPKCS7(self, pkcs7); + if(PKCS7_type_is_signed(pkcs7)){ + if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) + ossl_raise(ePKCS7Error, NULL); + } + if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; + for(;;){ + if((len = BIO_read(in, buf, sizeof(buf))) <= 0) + break; + if(BIO_write(out, buf, len) != len) + goto err; + } + if(!PKCS7_dataFinal(pkcs7, out)) goto err; + ossl_pkcs7_set_data(self, Qnil); + + err: + BIO_free(out); + BIO_free(in); + if(ERR_peek_error()){ + ossl_raise(ePKCS7Error, NULL); + } + + return data; +} + +static VALUE +ossl_pkcs7_to_der(VALUE self) +{ + PKCS7 *pkcs7; + VALUE str; + long len; + unsigned char *p; + + GetPKCS7(self, pkcs7); + if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) + ossl_raise(ePKCS7Error, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_PKCS7(pkcs7, &p) <= 0) + ossl_raise(ePKCS7Error, NULL); + ossl_str_adjust(str, p); + + return str; +} + +static VALUE +ossl_pkcs7_to_pem(VALUE self) +{ + PKCS7 *pkcs7; + BIO *out; + VALUE str; + + GetPKCS7(self, pkcs7); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(ePKCS7Error, NULL); + } + if (!PEM_write_bio_PKCS7(out, pkcs7)) { + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +/* + * SIGNER INFO + */ +static VALUE +ossl_pkcs7si_alloc(VALUE klass) +{ + PKCS7_SIGNER_INFO *p7si; + VALUE obj; + + if (!(p7si = PKCS7_SIGNER_INFO_new())) { + ossl_raise(ePKCS7Error, NULL); + } + WrapPKCS7si(klass, obj, p7si); + + return obj; +} + +static VALUE +ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) +{ + PKCS7_SIGNER_INFO *p7si; + EVP_PKEY *pkey; + X509 *x509; + const EVP_MD *md; + + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ + md = GetDigestPtr(digest); + GetPKCS7si(self, p7si); + if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { + ossl_raise(ePKCS7Error, NULL); + } + + return self; +} + +static VALUE +ossl_pkcs7si_get_issuer(VALUE self) +{ + PKCS7_SIGNER_INFO *p7si; + + GetPKCS7si(self, p7si); + + return ossl_x509name_new(p7si->issuer_and_serial->issuer); +} + +static VALUE +ossl_pkcs7si_get_serial(VALUE self) +{ + PKCS7_SIGNER_INFO *p7si; + + GetPKCS7si(self, p7si); + + return asn1integer_to_num(p7si->issuer_and_serial->serial); +} + +static VALUE +ossl_pkcs7si_get_signed_time(VALUE self) +{ + PKCS7_SIGNER_INFO *p7si; + ASN1_TYPE *asn1obj; + + GetPKCS7si(self, p7si); + + if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) { + ossl_raise(ePKCS7Error, NULL); + } + if (asn1obj->type == V_ASN1_UTCTIME) { + return asn1time_to_time(asn1obj->value.utctime); + } + /* + * OR + * ossl_raise(ePKCS7Error, "..."); + * ? + */ + + return Qnil; +} + +/* + * RECIPIENT INFO + */ +static VALUE +ossl_pkcs7ri_alloc(VALUE klass) +{ + PKCS7_RECIP_INFO *p7ri; + VALUE obj; + + if (!(p7ri = PKCS7_RECIP_INFO_new())) { + ossl_raise(ePKCS7Error, NULL); + } + WrapPKCS7ri(klass, obj, p7ri); + + return obj; +} + +static VALUE +ossl_pkcs7ri_initialize(VALUE self, VALUE cert) +{ + PKCS7_RECIP_INFO *p7ri; + X509 *x509; + + x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ + GetPKCS7ri(self, p7ri); + if (!PKCS7_RECIP_INFO_set(p7ri, x509)) { + ossl_raise(ePKCS7Error, NULL); + } + + return self; +} + +static VALUE +ossl_pkcs7ri_get_issuer(VALUE self) +{ + PKCS7_RECIP_INFO *p7ri; + + GetPKCS7ri(self, p7ri); + + return ossl_x509name_new(p7ri->issuer_and_serial->issuer); +} + +static VALUE +ossl_pkcs7ri_get_serial(VALUE self) +{ + PKCS7_RECIP_INFO *p7ri; + + GetPKCS7ri(self, p7ri); + + return asn1integer_to_num(p7ri->issuer_and_serial->serial); +} + +static VALUE +ossl_pkcs7ri_get_enc_key(VALUE self) +{ + PKCS7_RECIP_INFO *p7ri; + + GetPKCS7ri(self, p7ri); + + return asn1str_to_str(p7ri->enc_key); +} + +/* + * INIT + */ +void +Init_ossl_pkcs7() +{ + mPKCS7 = rb_define_module_under(mOSSL, "PKCS7"); + + ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError); + + cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject); + rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1); + rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1); + rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1); + rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1); + rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); + rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); + rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); + rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); + rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); + rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); + rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); + rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1); + rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0); + rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0); + rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1); + rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1); + rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); + rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1); + rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0); + rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); + rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1); + rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0); + rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); + rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1); + rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0); + rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1); + rb_define_alias(cPKCS7, "data=", "add_data"); + rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1); + rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); + rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); + rb_define_alias(cPKCS7, "to_s", "to_pem"); + rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); + + cPKCS7Signer = rb_define_class_under(mPKCS7, "SignerInfo", rb_cObject); + rb_define_const(mPKCS7, "Signer", cPKCS7Signer); + rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); + rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); + rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); + rb_define_alias(cPKCS7Signer, "name", "issuer"); + rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); + rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); + + cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject); + rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); + rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1); + rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0); + rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0); + rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0); + +#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x)) + + DefPKCS7Const(TEXT); + DefPKCS7Const(NOCERTS); + DefPKCS7Const(NOSIGS); + DefPKCS7Const(NOCHAIN); + DefPKCS7Const(NOINTERN); + DefPKCS7Const(NOVERIFY); + DefPKCS7Const(DETACHED); + DefPKCS7Const(BINARY); + DefPKCS7Const(NOATTR); + DefPKCS7Const(NOSMIMECAP); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs7.h b/ruby_1_8_5/ext/openssl/ossl_pkcs7.h new file mode 100644 index 0000000000..fdf0d9fb34 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkcs7.h @@ -0,0 +1,23 @@ +/* + * $Id: ossl_pkcs7.h,v 1.1.2.1 2005/09/10 01:17:00 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_PKCS7_H_) +#define _OSSL_PKCS7_H_ + +extern VALUE mPKCS7; +extern VALUE cPKCS7; +extern VALUE cPKCS7Signer; +extern VALUE cPKCS7Recipient; +extern VALUE ePKCS7Error; + +void Init_ossl_pkcs7(void); + +#endif /* _OSSL_PKCS7_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey.c b/ruby_1_8_5/ext/openssl/ossl_pkey.c new file mode 100644 index 0000000000..5a061597f6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkey.c @@ -0,0 +1,232 @@ +/* + * $Id: ossl_pkey.c,v 1.4.2.2 2005/04/08 09:26:54 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +/* + * Classes + */ +VALUE mPKey; +VALUE cPKey; +VALUE ePKeyError; +ID id_private_q; + +/* + * callback for generating keys + */ +void +ossl_generate_cb(int p, int n, void *arg) +{ + VALUE ary; + + ary = rb_ary_new2(2); + rb_ary_store(ary, 0, INT2NUM(p)); + rb_ary_store(ary, 1, INT2NUM(n)); + + rb_yield(ary); +} + +/* + * Public + */ +VALUE +ossl_pkey_new(EVP_PKEY *pkey) +{ + if (!pkey) { + ossl_raise(ePKeyError, "Cannot make new key from NULL."); + } + switch (EVP_PKEY_type(pkey->type)) { +#if !defined(OPENSSL_NO_RSA) + case EVP_PKEY_RSA: + return ossl_rsa_new(pkey); +#endif +#if !defined(OPENSSL_NO_DSA) + case EVP_PKEY_DSA: + return ossl_dsa_new(pkey); +#endif +#if !defined(OPENSSL_NO_DH) + case EVP_PKEY_DH: + return ossl_dh_new(pkey); +#endif + default: + ossl_raise(ePKeyError, "unsupported key type"); + } + return Qnil; /* not reached */ +} + +VALUE +ossl_pkey_new_from_file(VALUE filename) +{ + FILE *fp; + EVP_PKEY *pkey; + + SafeStringValue(filename); + if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) { + ossl_raise(ePKeyError, "%s", strerror(errno)); + } + + pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL); + fclose(fp); + if (!pkey) { + ossl_raise(ePKeyError, NULL); + } + + return ossl_pkey_new(pkey); +} + +EVP_PKEY * +GetPKeyPtr(VALUE obj) +{ + EVP_PKEY *pkey; + + SafeGetPKey(obj, pkey); + + return pkey; +} + +EVP_PKEY * +GetPrivPKeyPtr(VALUE obj) +{ + EVP_PKEY *pkey; + + if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { + ossl_raise(rb_eArgError, "Private key is needed."); + } + SafeGetPKey(obj, pkey); + + return pkey; +} + +EVP_PKEY * +DupPKeyPtr(VALUE obj) +{ + EVP_PKEY *pkey; + + SafeGetPKey(obj, pkey); + CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + + return pkey; +} + +EVP_PKEY * +DupPrivPKeyPtr(VALUE obj) +{ + EVP_PKEY *pkey; + + if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { + ossl_raise(rb_eArgError, "Private key is needed."); + } + SafeGetPKey(obj, pkey); + CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + + return pkey; +} + +/* + * Private + */ +static VALUE +ossl_pkey_alloc(VALUE klass) +{ + EVP_PKEY *pkey; + VALUE obj; + + if (!(pkey = EVP_PKEY_new())) { + ossl_raise(ePKeyError, NULL); + } + WrapPKey(klass, obj, pkey); + + return obj; +} + +static VALUE +ossl_pkey_initialize(VALUE self) +{ + if (rb_obj_is_instance_of(self, cPKey)) { + ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class."); + } + return self; +} + +static VALUE +ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) +{ + EVP_PKEY *pkey; + EVP_MD_CTX ctx; + int buf_len; + VALUE str; + + if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) { + ossl_raise(rb_eArgError, "Private key is needed."); + } + GetPKey(self, pkey); + EVP_SignInit(&ctx, GetDigestPtr(digest)); + StringValue(data); + EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len); + str = rb_str_new(0, EVP_PKEY_size(pkey)+16); + if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey)) + ossl_raise(ePKeyError, NULL); + assert(buf_len <= RSTRING(str)->len); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) +{ + EVP_PKEY *pkey; + EVP_MD_CTX ctx; + + GetPKey(self, pkey); + EVP_VerifyInit(&ctx, GetDigestPtr(digest)); + StringValue(sig); + StringValue(data); + EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len); + switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) { + case 0: + return Qfalse; + case 1: + return Qtrue; + default: + ossl_raise(ePKeyError, NULL); + } + return Qnil; /* dummy */ +} + +/* + * INIT + */ +void +Init_ossl_pkey() +{ + mPKey = rb_define_module_under(mOSSL, "PKey"); + + ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError); + + cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject); + + rb_define_alloc_func(cPKey, ossl_pkey_alloc); + rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); + + rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); + rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); + + id_private_q = rb_intern("private?"); + + /* + * INIT rsa, dsa + */ + Init_ossl_rsa(); + Init_ossl_dsa(); + Init_ossl_dh(); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey.h b/ruby_1_8_5/ext/openssl/ossl_pkey.h new file mode 100644 index 0000000000..224f0f4634 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkey.h @@ -0,0 +1,120 @@ +/* + * $Id: ossl_pkey.h,v 1.2.2.2 2005/09/18 22:56:11 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_PKEY_H_) +#define _OSSL_PKEY_H_ + +extern VALUE mPKey; +extern VALUE cPKey; +extern VALUE ePKeyError; +extern ID id_private_q; + +#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue) +#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse) +#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue) + +#define WrapPKey(klass, obj, pkey) do { \ + if (!pkey) { \ + rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, EVP_PKEY_free, pkey); \ + OSSL_PKEY_SET_PUBLIC(obj); \ +} while (0) +#define GetPKey(obj, pkey) do {\ + Data_Get_Struct(obj, EVP_PKEY, pkey);\ + if (!pkey) { \ + rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\ + } \ +} while (0) +#define SafeGetPKey(obj, pkey) do { \ + OSSL_Check_Kind(obj, cPKey); \ + GetPKey(obj, pkey); \ +} while (0) + +void ossl_generate_cb(int, int, void *); + +VALUE ossl_pkey_new(EVP_PKEY *); +VALUE ossl_pkey_new_from_file(VALUE); +EVP_PKEY *GetPKeyPtr(VALUE); +EVP_PKEY *DupPKeyPtr(VALUE); +EVP_PKEY *GetPrivPKeyPtr(VALUE); +EVP_PKEY *DupPrivPKeyPtr(VALUE); +void Init_ossl_pkey(void); + +/* + * RSA + */ +extern VALUE cRSA; +extern VALUE eRSAError; + +VALUE ossl_rsa_new(EVP_PKEY *); +void Init_ossl_rsa(void); + +/* + * DSA + */ +extern VALUE cDSA; +extern VALUE eDSAError; + +VALUE ossl_dsa_new(EVP_PKEY *); +void Init_ossl_dsa(void); + +/* + * DH + */ +extern VALUE cDH; +extern VALUE eDHError; +extern DH *OSSL_DEFAULT_DH_512; +extern DH *OSSL_DEFAULT_DH_1024; + +VALUE ossl_dh_new(EVP_PKEY *); +void Init_ossl_dh(void); + +#define OSSL_PKEY_BN(keytype, name) \ +static VALUE ossl_##keytype##_get_##name(VALUE self) \ +{ \ + EVP_PKEY *pkey; \ + BIGNUM *bn; \ + \ + GetPKey(self, pkey); \ + bn = pkey->pkey.keytype->name; \ + if (bn == NULL) \ + return Qnil; \ + return ossl_bn_new(bn); \ +} \ +static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \ +{ \ + EVP_PKEY *pkey; \ + BIGNUM *bn; \ + \ + GetPKey(self, pkey); \ + if (NIL_P(bignum)) { \ + BN_clear_free(pkey->pkey.keytype->name); \ + pkey->pkey.keytype->name = NULL; \ + return Qnil; \ + } \ + \ + bn = GetBNPtr(bignum); \ + if (pkey->pkey.keytype->name == NULL) \ + pkey->pkey.keytype->name = BN_new(); \ + if (pkey->pkey.keytype->name == NULL) \ + ossl_raise(eBNError, NULL); \ + if (BN_copy(pkey->pkey.keytype->name, bn) == NULL) \ + ossl_raise(eBNError, NULL); \ + return bignum; \ +} + +#define DEF_OSSL_PKEY_BN(class, keytype, name) \ +do { \ + rb_define_method(class, #name, ossl_##keytype##_get_##name, 0); \ + rb_define_method(class, #name "=", ossl_##keytype##_set_##name, 1);\ +} while (0) + +#endif /* _OSSL_PKEY_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c b/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c new file mode 100644 index 0000000000..79692f2f47 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c @@ -0,0 +1,458 @@ +/* + * $Id: ossl_pkey_dh.c,v 1.4.2.3 2005/04/08 09:26:54 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(OPENSSL_NO_DH) + +#include "ossl.h" + +#define GetPKeyDH(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \ + } \ +} while (0) + +#define DH_HAS_PRIVATE(dh) ((dh)->priv_key) + +#ifdef OSSL_ENGINE_ENABLED +# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine) +#else +# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh) +#endif + + +/* + * Classes + */ +VALUE cDH; +VALUE eDHError; + +/* + * Public + */ +static VALUE +dh_instance(VALUE klass, DH *dh) +{ + EVP_PKEY *pkey; + VALUE obj; + + if (!dh) { + return Qfalse; + } + if (!(pkey = EVP_PKEY_new())) { + return Qfalse; + } + if (!EVP_PKEY_assign_DH(pkey, dh)) { + EVP_PKEY_free(pkey); + return Qfalse; + } + WrapPKey(klass, obj, pkey); + + return obj; +} + +VALUE +ossl_dh_new(EVP_PKEY *pkey) +{ + VALUE obj; + + if (!pkey) { + obj = dh_instance(cDH, DH_new()); + } else { + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { + ossl_raise(rb_eTypeError, "Not a DH key!"); + } + WrapPKey(cDH, obj, pkey); + } + if (obj == Qfalse) { + ossl_raise(eDHError, NULL); + } + + return obj; +} + +/* + * Private + */ +static DH * +dh_generate(int size, int gen) +{ + DH *dh; + + dh = DH_generate_parameters(size, gen, + rb_block_given_p() ? ossl_generate_cb : NULL, + NULL); + if (!dh) return 0; + + if (!DH_generate_key(dh)) { + DH_free(dh); + return 0; + } + + return dh; +} + +static VALUE +ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) +{ + DH *dh ; + int g = 2; + VALUE size, gen, obj; + + if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) { + g = FIX2INT(gen); + } + dh = dh_generate(FIX2INT(size), g); + obj = dh_instance(klass, dh); + if (obj == Qfalse) { + DH_free(dh); + ossl_raise(eDHError, NULL); + } + + return obj; +} + +static VALUE +ossl_dh_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + DH *dh; + int g = 2; + BIO *in; + VALUE arg, gen; + + GetPKey(self, pkey); + if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) { + dh = DH_new(); + } + else if (FIXNUM_P(arg)) { + if (!NIL_P(gen)) { + g = FIX2INT(gen); + } + if (!(dh = dh_generate(FIX2INT(arg), g))) { + ossl_raise(eDHError, NULL); + } + } + else { + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (!dh){ + BIO_reset(in); + dh = d2i_DHparams_bio(in, NULL); + } + BIO_free(in); + if (!dh) ossl_raise(eDHError, NULL); + } + if (!EVP_PKEY_assign_DH(pkey, dh)) { + DH_free(dh); + ossl_raise(eDHError, NULL); + } + return self; +} + +static VALUE +ossl_dh_is_public(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyDH(self, pkey); + /* + * Do we need to check dhp->dh->public_pkey? + * return Qtrue; + */ + return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse; +} + +static VALUE +ossl_dh_is_private(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyDH(self, pkey); + + return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse; +} + +static VALUE +ossl_dh_export(VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + VALUE str; + + GetPKeyDH(self, pkey); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eDHError, NULL); + } + if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) { + BIO_free(out); + ossl_raise(eDHError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_dh_to_der(VALUE self) +{ + EVP_PKEY *pkey; + unsigned char *p; + long len; + VALUE str; + + GetPKeyDH(self, pkey); + if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0) + ossl_raise(eDHError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_DHparams(pkey->pkey.dh, &p) < 0) + ossl_raise(eDHError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * Stores all parameters of key to the hash + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (I's up to you) + */ +static VALUE +ossl_dh_get_params(VALUE self) +{ + EVP_PKEY *pkey; + VALUE hash; + + GetPKeyDH(self, pkey); + + hash = rb_hash_new(); + + rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p)); + rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g)); + rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key)); + rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key)); + + return hash; +} + +/* + * Prints all parameters of key to buffer + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (I's up to you) + */ +static VALUE +ossl_dh_to_text(VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + VALUE str; + + GetPKeyDH(self, pkey); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eDHError, NULL); + } + if (!DHparams_print(out, pkey->pkey.dh)) { + BIO_free(out); + ossl_raise(eDHError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +/* + * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY + */ +static VALUE +ossl_dh_to_public_key(VALUE self) +{ + EVP_PKEY *pkey; + DH *dh; + VALUE obj; + + GetPKeyDH(self, pkey); + dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */ + obj = dh_instance(CLASS_OF(self), dh); + if (obj == Qfalse) { + DH_free(dh); + ossl_raise(eDHError, NULL); + } + + return obj; +} + +static VALUE +ossl_dh_check_params(VALUE self) +{ + DH *dh; + EVP_PKEY *pkey; + int codes; + + GetPKeyDH(self, pkey); + dh = pkey->pkey.dh; + + if (!DH_check(dh, &codes)) { + return Qfalse; + } + + return codes == 0 ? Qtrue : Qfalse; +} + +static VALUE +ossl_dh_generate_key(VALUE self) +{ + DH *dh; + EVP_PKEY *pkey; + + GetPKeyDH(self, pkey); + dh = pkey->pkey.dh; + + if (!DH_generate_key(dh)) + ossl_raise(eDHError, "Failed to generate key"); + return self; +} + +static VALUE +ossl_dh_compute_key(VALUE self, VALUE pub) +{ + DH *dh; + EVP_PKEY *pkey; + BIGNUM *pub_key; + VALUE str; + int len; + + GetPKeyDH(self, pkey); + dh = pkey->pkey.dh; + pub_key = GetBNPtr(pub); + len = DH_size(dh); + str = rb_str_new(0, len); + if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) { + ossl_raise(eDHError, NULL); + } + RSTRING(str)->len = len; + RSTRING(str)->ptr[len] = 0; + + return str; +} + +OSSL_PKEY_BN(dh, p); +OSSL_PKEY_BN(dh, g); +OSSL_PKEY_BN(dh, pub_key); +OSSL_PKEY_BN(dh, priv_key); + +/* + * -----BEGIN DH PARAMETERS----- + * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2 + * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC + * -----END DH PARAMETERS----- + */ +static unsigned char DEFAULT_DH_512_PRIM[] = { + 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98, + 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c, + 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba, + 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8, + 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a, + 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5, + 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31, + 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb, +}; +static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 }; +DH *OSSL_DEFAULT_DH_512 = NULL; + +/* + * -----BEGIN DH PARAMETERS----- + * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ + * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR + * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC + * -----END DH PARAMETERS----- + */ +static unsigned char DEFAULT_DH_1024_PRIM[] = { + 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff, + 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d, + 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74, + 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7, + 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c, + 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d, + 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60, + 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31, + 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f, + 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f, + 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11, + 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce, + 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54, + 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12, + 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14, + 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83 +}; +static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 }; +DH *OSSL_DEFAULT_DH_1024 = NULL; + +static DH* +ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen) +{ + DH *dh; + + if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL); + dh->p = BN_bin2bn(p, plen, NULL); + dh->g = BN_bin2bn(g, glen, NULL); + if (dh->p == NULL || dh->g == NULL){ + DH_free(dh); + ossl_raise(eDHError, NULL); + } + + return dh; +} + +/* + * INIT + */ +void +Init_ossl_dh() +{ + eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError); + cDH = rb_define_class_under(mPKey, "DH", cPKey); + rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); + rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); + rb_define_method(cDH, "public?", ossl_dh_is_public, 0); + rb_define_method(cDH, "private?", ossl_dh_is_private, 0); + rb_define_method(cDH, "to_text", ossl_dh_to_text, 0); + rb_define_method(cDH, "export", ossl_dh_export, 0); + rb_define_alias(cDH, "to_pem", "export"); + rb_define_alias(cDH, "to_s", "export"); + rb_define_method(cDH, "to_der", ossl_dh_to_der, 0); + rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0); + rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0); + rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0); + rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); + DEF_OSSL_PKEY_BN(cDH, dh, p); + DEF_OSSL_PKEY_BN(cDH, dh, g); + DEF_OSSL_PKEY_BN(cDH, dh, pub_key); + DEF_OSSL_PKEY_BN(cDH, dh, priv_key); + rb_define_method(cDH, "params", ossl_dh_get_params, 0); + + OSSL_DEFAULT_DH_512 = ossl_create_dh( + DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM), + DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN)); + OSSL_DEFAULT_DH_1024 = ossl_create_dh( + DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM), + DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN)); +} + +#else /* defined NO_DH */ +# warning >>> OpenSSL is compiled without DH support <<< +void +Init_ossl_dh() +{ + rb_warning("OpenSSL is compiled without DH support"); +} +#endif /* NO_DH */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c b/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c new file mode 100644 index 0000000000..2a6060fe77 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c @@ -0,0 +1,417 @@ +/* + * $Id: ossl_pkey_dsa.c,v 1.5.2.3 2005/09/18 22:56:11 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(OPENSSL_NO_DSA) + +#include "ossl.h" + +#define GetPKeyDSA(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \ + } \ +} while (0) + +#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key) +#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj)) + +/* + * Classes + */ +VALUE cDSA; +VALUE eDSAError; + +/* + * Public + */ +static VALUE +dsa_instance(VALUE klass, DSA *dsa) +{ + EVP_PKEY *pkey; + VALUE obj; + + if (!dsa) { + return Qfalse; + } + if (!(pkey = EVP_PKEY_new())) { + return Qfalse; + } + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { + EVP_PKEY_free(pkey); + return Qfalse; + } + WrapPKey(klass, obj, pkey); + + return obj; +} + +VALUE +ossl_dsa_new(EVP_PKEY *pkey) +{ + VALUE obj; + + if (!pkey) { + obj = dsa_instance(cDSA, DSA_new()); + } else { + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { + ossl_raise(rb_eTypeError, "Not a DSA key!"); + } + WrapPKey(cDSA, obj, pkey); + } + if (obj == Qfalse) { + ossl_raise(eDSAError, NULL); + } + + return obj; +} + +/* + * Private + */ +static DSA * +dsa_generate(int size) +{ + DSA *dsa; + unsigned char seed[20]; + int seed_len = 20, counter; + unsigned long h; + + if (!RAND_bytes(seed, seed_len)) { + return 0; + } + dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h, + rb_block_given_p() ? ossl_generate_cb : NULL, + NULL); + if(!dsa) return 0; + + if (!DSA_generate_key(dsa)) { + DSA_free(dsa); + return 0; + } + + return dsa; +} + +static VALUE +ossl_dsa_s_generate(VALUE klass, VALUE size) +{ + DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */ + VALUE obj = dsa_instance(klass, dsa); + + if (obj == Qfalse) { + DSA_free(dsa); + ossl_raise(eDSAError, NULL); + } + + return obj; +} + +static VALUE +ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + DSA *dsa; + BIO *in; + char *passwd = NULL; + VALUE arg, pass; + + GetPKey(self, pkey); + if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { + dsa = DSA_new(); + } + else if (FIXNUM_P(arg)) { + if (!(dsa = dsa_generate(FIX2INT(arg)))) { + ossl_raise(eDSAError, NULL); + } + } + else { + if (!NIL_P(pass)) passwd = StringValuePtr(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); + if (!dsa) { + BIO_reset(in); + dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); + } + if (!dsa) { + BIO_reset(in); + dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); + } + if (!dsa) { + BIO_reset(in); + dsa = d2i_DSAPrivateKey_bio(in, NULL); + } + if (!dsa) { + BIO_reset(in); + dsa = d2i_DSA_PUBKEY_bio(in, NULL); + } + BIO_free(in); + if (!dsa) ossl_raise(eDSAError, "Neither PUB key nor PRIV key:"); + } + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { + DSA_free(dsa); + ossl_raise(eDSAError, NULL); + } + + return self; +} + +static VALUE +ossl_dsa_is_public(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyDSA(self, pkey); + + /* + * Do we need to check dsap->dsa->public_pkey? + * return Qtrue; + */ + return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse; +} + +static VALUE +ossl_dsa_is_private(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyDSA(self, pkey); + + return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse; +} + +static VALUE +ossl_dsa_export(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + const EVP_CIPHER *ciph = NULL; + char *passwd = NULL; + VALUE cipher, pass, str; + + GetPKeyDSA(self, pkey); + rb_scan_args(argc, argv, "02", &cipher, &pass); + if (!NIL_P(cipher)) { + ciph = GetCipherPtr(cipher); + if (!NIL_P(pass)) { + passwd = StringValuePtr(pass); + } + } + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eDSAError, NULL); + } + if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) { + if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph, + NULL, 0, ossl_pem_passwd_cb, passwd)){ + BIO_free(out); + ossl_raise(eDSAError, NULL); + } + } else { + if (!PEM_write_bio_DSAPublicKey(out, pkey->pkey.dsa)) { + BIO_free(out); + ossl_raise(eDSAError, NULL); + } + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_dsa_to_der(VALUE self) +{ + EVP_PKEY *pkey; + int (*i2d_func)_((DSA*, unsigned char**)); + unsigned char *p; + long len; + VALUE str; + + GetPKeyDSA(self, pkey); + if(DSA_HAS_PRIVATE(pkey->pkey.dsa)) + i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey; + else + i2d_func = i2d_DSA_PUBKEY; + if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0) + ossl_raise(eDSAError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_func(pkey->pkey.dsa, &p) < 0) + ossl_raise(eDSAError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * Stores all parameters of key to the hash + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (I's up to you) + */ +static VALUE +ossl_dsa_get_params(VALUE self) +{ + EVP_PKEY *pkey; + VALUE hash; + + GetPKeyDSA(self, pkey); + + hash = rb_hash_new(); + + rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p)); + rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q)); + rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g)); + rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key)); + rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key)); + + return hash; +} + +/* + * Prints all parameters of key to buffer + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (I's up to you) + */ +static VALUE +ossl_dsa_to_text(VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + VALUE str; + + GetPKeyDSA(self, pkey); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eDSAError, NULL); + } + if (!DSA_print(out, pkey->pkey.dsa, 0)) { /* offset = 0 */ + BIO_free(out); + ossl_raise(eDSAError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +/* + * Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY + */ +static VALUE +ossl_dsa_to_public_key(VALUE self) +{ + EVP_PKEY *pkey; + DSA *dsa; + VALUE obj; + + GetPKeyDSA(self, pkey); + /* err check performed by dsa_instance */ + dsa = DSAPublicKey_dup(pkey->pkey.dsa); + obj = dsa_instance(CLASS_OF(self), dsa); + if (obj == Qfalse) { + DSA_free(dsa); + ossl_raise(eDSAError, NULL); + } + return obj; +} + +#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16) + +static VALUE +ossl_dsa_sign(VALUE self, VALUE data) +{ + EVP_PKEY *pkey; + int buf_len; + VALUE str; + + GetPKeyDSA(self, pkey); + StringValue(data); + if (!DSA_PRIVATE(self, pkey->pkey.dsa)) { + ossl_raise(eDSAError, "Private DSA key needed!"); + } + str = rb_str_new(0, ossl_dsa_buf_size(pkey)); + if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr, + &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */ + ossl_raise(eDSAError, NULL); + } + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) +{ + EVP_PKEY *pkey; + int ret; + + GetPKeyDSA(self, pkey); + StringValue(digest); + StringValue(sig); + /* type is ignored (0) */ + ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len, + RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa); + if (ret < 0) { + ossl_raise(eDSAError, NULL); + } + else if (ret == 1) { + return Qtrue; + } + + return Qfalse; +} + +OSSL_PKEY_BN(dsa, p); +OSSL_PKEY_BN(dsa, q); +OSSL_PKEY_BN(dsa, g); +OSSL_PKEY_BN(dsa, pub_key); +OSSL_PKEY_BN(dsa, priv_key); + +/* + * INIT + */ +void +Init_ossl_dsa() +{ + eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError); + + cDSA = rb_define_class_under(mPKey, "DSA", cPKey); + + rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); + rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); + + rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); + rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); + rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0); + rb_define_method(cDSA, "export", ossl_dsa_export, -1); + rb_define_alias(cDSA, "to_pem", "export"); + rb_define_alias(cDSA, "to_s", "export"); + rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0); + rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0); + rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1); + rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2); + + DEF_OSSL_PKEY_BN(cDSA, dsa, p); + DEF_OSSL_PKEY_BN(cDSA, dsa, q); + DEF_OSSL_PKEY_BN(cDSA, dsa, g); + DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key); + DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key); + + rb_define_method(cDSA, "params", ossl_dsa_get_params, 0); +} + +#else /* defined NO_DSA */ +# warning >>> OpenSSL is compiled without DSA support <<< + +void +Init_ossl_dsa() +{ + rb_warning("OpenSSL is compiled without DSA support"); +} + +#endif /* NO_DSA */ diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c b/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c new file mode 100644 index 0000000000..69d69c76f4 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c @@ -0,0 +1,513 @@ +/* + * $Id: ossl_pkey_rsa.c,v 1.5.2.4 2005/09/18 22:56:11 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(OPENSSL_NO_RSA) + +#include "ossl.h" + +#define GetPKeyRSA(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \ + ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \ + } \ +} while (0) + +#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q) +#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj)) + +/* + * Classes + */ +VALUE cRSA; +VALUE eRSAError; + +/* + * Public + */ +static VALUE +rsa_instance(VALUE klass, RSA *rsa) +{ + EVP_PKEY *pkey; + VALUE obj; + + if (!rsa) { + return Qfalse; + } + if (!(pkey = EVP_PKEY_new())) { + return Qfalse; + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + EVP_PKEY_free(pkey); + return Qfalse; + } + WrapPKey(klass, obj, pkey); + + return obj; +} + +VALUE +ossl_rsa_new(EVP_PKEY *pkey) +{ + VALUE obj; + + if (!pkey) { + obj = rsa_instance(cRSA, RSA_new()); + } + else { + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { + ossl_raise(rb_eTypeError, "Not a RSA key!"); + } + WrapPKey(cRSA, obj, pkey); + } + if (obj == Qfalse) { + ossl_raise(eRSAError, NULL); + } + + return obj; +} + +/* + * Private + */ +static RSA * +rsa_generate(int size, int exp) +{ + return RSA_generate_key(size, exp, + rb_block_given_p() ? ossl_generate_cb : NULL, + NULL); +} + +static VALUE +ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) +{ + RSA *rsa; + VALUE size, exp; + VALUE obj; + + rb_scan_args(argc, argv, "11", &size, &exp); + + rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2INT(exp)); /* err handled by rsa_instance */ + obj = rsa_instance(klass, rsa); + + if (obj == Qfalse) { + RSA_free(rsa); + ossl_raise(eRSAError, NULL); + } + + return obj; +} + +static VALUE +ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + RSA *rsa; + BIO *in; + char *passwd = NULL; + VALUE arg, pass; + + GetPKey(self, pkey); + if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { + rsa = RSA_new(); + } + else if (FIXNUM_P(arg)) { + rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass)); + if (!rsa) ossl_raise(eRSAError, NULL); + } + else { + if (!NIL_P(pass)) passwd = StringValuePtr(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); + if (!rsa) { + BIO_reset(in); + rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); + } + if (!rsa) { + BIO_reset(in); + rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); + } + if (!rsa) { + BIO_reset(in); + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } + if (!rsa) { + BIO_reset(in); + rsa = d2i_RSAPublicKey_bio(in, NULL); + } + if (!rsa) { + BIO_reset(in); + rsa = d2i_RSA_PUBKEY_bio(in, NULL); + } + BIO_free(in); + if (!rsa) ossl_raise(eRSAError, "Neither PUB key nor PRIV key:"); + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + RSA_free(rsa); + ossl_raise(eRSAError, NULL); + } + + return self; +} + +static VALUE +ossl_rsa_is_public(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyRSA(self, pkey); + /* + * SURPRISE! :-)) + * Every key is public at the same time! + */ + return Qtrue; +} + +static VALUE +ossl_rsa_is_private(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyRSA(self, pkey); + + return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse; +} + +static VALUE +ossl_rsa_export(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + const EVP_CIPHER *ciph = NULL; + char *passwd = NULL; + VALUE cipher, pass, str; + + GetPKeyRSA(self, pkey); + + rb_scan_args(argc, argv, "02", &cipher, &pass); + + if (!NIL_P(cipher)) { + ciph = GetCipherPtr(cipher); + if (!NIL_P(pass)) { + passwd = StringValuePtr(pass); + } + } + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eRSAError, NULL); + } + if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) { + if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, + NULL, 0, ossl_pem_passwd_cb, passwd)) { + BIO_free(out); + ossl_raise(eRSAError, NULL); + } + } else { + if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) { + BIO_free(out); + ossl_raise(eRSAError, NULL); + } + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_rsa_to_der(VALUE self) +{ + EVP_PKEY *pkey; + int (*i2d_func)_((const RSA*, unsigned char**)); + unsigned char *p; + long len; + VALUE str; + + GetPKeyRSA(self, pkey); + if(RSA_HAS_PRIVATE(pkey->pkey.rsa)) + i2d_func = i2d_RSAPrivateKey; + else + i2d_func = i2d_RSAPublicKey; + if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0) + ossl_raise(eRSAError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_func(pkey->pkey.rsa, &p) < 0) + ossl_raise(eRSAError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) + +static VALUE +ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + int buf_len, pad; + VALUE str, buffer, padding; + + GetPKeyRSA(self, pkey); + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); + StringValue(buffer); + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, + RSTRING(str)->ptr, pkey->pkey.rsa, + pad); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + int buf_len, pad; + VALUE str, buffer, padding; + + GetPKeyRSA(self, pkey); + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); + StringValue(buffer); + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, + RSTRING(str)->ptr, pkey->pkey.rsa, + pad); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + int buf_len, pad; + VALUE str, buffer, padding; + + GetPKeyRSA(self, pkey); + if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { + ossl_raise(eRSAError, "private key needed."); + } + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); + StringValue(buffer); + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, + RSTRING(str)->ptr, pkey->pkey.rsa, + pad); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + int buf_len, pad; + VALUE str, buffer, padding; + + GetPKeyRSA(self, pkey); + if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { + ossl_raise(eRSAError, "private key needed."); + } + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); + StringValue(buffer); + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, + RSTRING(str)->ptr, pkey->pkey.rsa, + pad); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +/* + * Stores all parameters of key to the hash + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (I's up to you) + */ +static VALUE +ossl_rsa_get_params(VALUE self) +{ + EVP_PKEY *pkey; + VALUE hash; + + GetPKeyRSA(self, pkey); + + hash = rb_hash_new(); + + rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n)); + rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e)); + rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d)); + rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p)); + rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q)); + rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1)); + rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1)); + rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp)); + + return hash; +} + +/* + * Prints all parameters of key to buffer + * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! + * Don't use :-)) (It's up to you) + */ +static VALUE +ossl_rsa_to_text(VALUE self) +{ + EVP_PKEY *pkey; + BIO *out; + VALUE str; + + GetPKeyRSA(self, pkey); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eRSAError, NULL); + } + if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */ + BIO_free(out); + ossl_raise(eRSAError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +/* + * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY + */ +static VALUE +ossl_rsa_to_public_key(VALUE self) +{ + EVP_PKEY *pkey; + RSA *rsa; + VALUE obj; + + GetPKeyRSA(self, pkey); + /* err check performed by rsa_instance */ + rsa = RSAPublicKey_dup(pkey->pkey.rsa); + obj = rsa_instance(CLASS_OF(self), rsa); + if (obj == Qfalse) { + RSA_free(rsa); + ossl_raise(eRSAError, NULL); + } + return obj; +} + +/* + * TODO: Test me +extern BN_CTX *ossl_bn_ctx; + +static VALUE +ossl_rsa_blinding_on(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyRSA(self, pkey); + + if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) { + ossl_raise(eRSAError, NULL); + } + return self; +} + +static VALUE +ossl_rsa_blinding_off(VALUE self) +{ + EVP_PKEY *pkey; + + GetPKeyRSA(self, pkey); + RSA_blinding_off(pkey->pkey.rsa); + + return self; +} + */ + +OSSL_PKEY_BN(rsa, n); +OSSL_PKEY_BN(rsa, e); +OSSL_PKEY_BN(rsa, d); +OSSL_PKEY_BN(rsa, p); +OSSL_PKEY_BN(rsa, q); +OSSL_PKEY_BN(rsa, dmp1); +OSSL_PKEY_BN(rsa, dmq1); +OSSL_PKEY_BN(rsa, iqmp); + +/* + * INIT + */ +#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x)) + +void +Init_ossl_rsa() +{ + eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError); + + cRSA = rb_define_class_under(mPKey, "RSA", cPKey); + + rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1); + rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); + + rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); + rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); + rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0); + rb_define_method(cRSA, "export", ossl_rsa_export, -1); + rb_define_alias(cRSA, "to_pem", "export"); + rb_define_alias(cRSA, "to_s", "export"); + rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); + rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0); + rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1); + rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1); + rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1); + rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1); + + DEF_OSSL_PKEY_BN(cRSA, rsa, n); + DEF_OSSL_PKEY_BN(cRSA, rsa, e); + DEF_OSSL_PKEY_BN(cRSA, rsa, d); + DEF_OSSL_PKEY_BN(cRSA, rsa, p); + DEF_OSSL_PKEY_BN(cRSA, rsa, q); + DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1); + DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1); + DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp); + + rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); + + DefRSAConst(PKCS1_PADDING); + DefRSAConst(SSLV23_PADDING); + DefRSAConst(NO_PADDING); + DefRSAConst(PKCS1_OAEP_PADDING); + +/* + * TODO: Test it + rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0); + rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0); + */ +} + +#else /* defined NO_RSA */ +# warning >>> OpenSSL is compiled without RSA support <<< +void +Init_ossl_rsa() +{ + rb_warning("OpenSSL is compiled without RSA support"); +} +#endif /* NO_RSA */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_rand.c b/ruby_1_8_5/ext/openssl/ossl_rand.c new file mode 100644 index 0000000000..ffd68966ca --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_rand.c @@ -0,0 +1,130 @@ +/* + * $Id: ossl_rand.c,v 1.2 2003/09/17 09:05:02 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +/* + * Classes + */ +VALUE mRandom; +VALUE eRandomError; + +/* + * Struct + */ + +/* + * Public + */ + +/* + * Private + */ +static VALUE +ossl_rand_seed(VALUE self, VALUE str) +{ + StringValue(str); + RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len); + + return str; +} + +static VALUE +ossl_rand_load_file(VALUE self, VALUE filename) +{ + SafeStringValue(filename); + + if(!RAND_load_file(RSTRING(filename)->ptr, -1)) { + ossl_raise(eRandomError, NULL); + } + return Qtrue; +} + +static VALUE +ossl_rand_write_file(VALUE self, VALUE filename) +{ + SafeStringValue(filename); + if (RAND_write_file(RSTRING(filename)->ptr) == -1) { + ossl_raise(eRandomError, NULL); + } + return Qtrue; +} + +static VALUE +ossl_rand_bytes(VALUE self, VALUE len) +{ + VALUE str; + + str = rb_str_new(0, FIX2INT(len)); + if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) { + ossl_raise(eRandomError, NULL); + } + + return str; +} + +static VALUE +ossl_rand_pseudo_bytes(VALUE self, VALUE len) +{ + VALUE str; + + str = rb_str_new(0, FIX2INT(len)); + if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) { + ossl_raise(eRandomError, NULL); + } + + return str; +} + +static VALUE +ossl_rand_egd(VALUE self, VALUE filename) +{ + SafeStringValue(filename); + + if(!RAND_egd(RSTRING(filename)->ptr)) { + ossl_raise(eRandomError, NULL); + } + return Qtrue; +} + +static VALUE +ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len) +{ + SafeStringValue(filename); + + if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) { + ossl_raise(eRandomError, NULL); + } + return Qtrue; +} + +#define DEFMETH(class, name, func, argc) \ + rb_define_method(class, name, func, argc); \ + rb_define_singleton_method(class, name, func, argc); + +/* + * INIT + */ +void +Init_ossl_rand() +{ + mRandom = rb_define_module_under(mOSSL, "Random"); + + eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError); + + DEFMETH(mRandom, "seed", ossl_rand_seed, 1); + DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1); + DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1); + DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1); + DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1); + DEFMETH(mRandom, "egd", ossl_rand_egd, 1); + DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_rand.h b/ruby_1_8_5/ext/openssl/ossl_rand.h new file mode 100644 index 0000000000..4895267fb6 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_rand.h @@ -0,0 +1,20 @@ +/* + * $Id: ossl_rand.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_RAND_H_) +#define _OSSL_RAND_H_ + +extern VALUE mRandom; +extern VALUE eRandomError; + +void Init_ossl_rand(void); + +#endif /* _OSSL_RAND_H_ */ + diff --git a/ruby_1_8_5/ext/openssl/ossl_ssl.c b/ruby_1_8_5/ext/openssl/ossl_ssl.c new file mode 100644 index 0000000000..e4889d6d3f --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ssl.c @@ -0,0 +1,937 @@ +/* + * $Id: ossl_ssl.c,v 1.13.2.11 2006/03/17 10:10:53 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2000-2002 GOTOU Yuuzou + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" +#include +#include + +#if defined(HAVE_UNISTD_H) +# include /* for read(), and write() */ +#endif + +#define numberof(ary) (sizeof(ary)/sizeof(ary[0])) + +#ifdef _WIN32 +# define TO_SOCKET(s) _get_osfhandle(s) +#else +# define TO_SOCKET(s) s +#endif + +VALUE mSSL; +VALUE eSSLError; +VALUE cSSLContext; +VALUE cSSLSocket; + +/* + * SSLContext class + */ +#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v)) +#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v)) +#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v)) +#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v)) +#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v)) +#define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v)) +#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v)) +#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v)) +#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v)) +#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v)) +#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v)) +#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v)) +#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v)) +#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v)) +#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v)) + +#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert") +#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key") +#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca") +#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file") +#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path") +#define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout") +#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode") +#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth") +#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback") +#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options") +#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store") +#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert") +#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb") +#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback") +#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context") + +static char *ossl_sslctx_attrs[] = { + "cert", "key", "client_ca", "ca_file", "ca_path", + "timeout", "verify_mode", "verify_depth", + "verify_callback", "options", "cert_store", "extra_chain_cert", + "client_cert_cb", "tmp_dh_callback", "session_id_context", +}; + +#define ossl_ssl_get_io(o) rb_iv_get((o),"@io") +#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context") +#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close") +#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509") +#define ossl_ssl_get_key(o) rb_iv_get((o),"@key") +#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh") + +#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v)) +#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v)) +#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v)) +#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v)) +#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v)) +#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v)) + +static char *ossl_ssl_attr_readers[] = { "io", "context", }; +static char *ossl_ssl_attrs[] = { "sync_close", }; + +/* + * SSLContext class + */ +struct { + const char *name; + SSL_METHOD *(*func)(void); +} ossl_ssl_method_tab[] = { +#define OSSL_SSL_METHOD_ENTRY(name) { #name, name##_method } + OSSL_SSL_METHOD_ENTRY(TLSv1), + OSSL_SSL_METHOD_ENTRY(TLSv1_server), + OSSL_SSL_METHOD_ENTRY(TLSv1_client), + OSSL_SSL_METHOD_ENTRY(SSLv2), + OSSL_SSL_METHOD_ENTRY(SSLv2_server), + OSSL_SSL_METHOD_ENTRY(SSLv2_client), + OSSL_SSL_METHOD_ENTRY(SSLv3), + OSSL_SSL_METHOD_ENTRY(SSLv3_server), + OSSL_SSL_METHOD_ENTRY(SSLv3_client), + OSSL_SSL_METHOD_ENTRY(SSLv23), + OSSL_SSL_METHOD_ENTRY(SSLv23_server), + OSSL_SSL_METHOD_ENTRY(SSLv23_client), +#undef OSSL_SSL_METHOD_ENTRY +}; + +int ossl_ssl_ex_vcb_idx; +int ossl_ssl_ex_store_p; +int ossl_ssl_ex_ptr_idx; +int ossl_ssl_ex_client_cert_cb_idx; +int ossl_ssl_ex_tmp_dh_callback_idx; + +static void +ossl_sslctx_free(SSL_CTX *ctx) +{ + if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1) + ctx->cert_store = NULL; + SSL_CTX_free(ctx); +} + +static VALUE +ossl_sslctx_s_alloc(VALUE klass) +{ + SSL_CTX *ctx; + + ctx = SSL_CTX_new(SSLv23_method()); + if (!ctx) { + ossl_raise(eSSLError, "SSL_CTX_new:"); + } + SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + SSL_CTX_set_options(ctx, SSL_OP_ALL); + return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx); +} + +static VALUE +ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE ssl_method; + SSL_METHOD *method = NULL; + SSL_CTX *ctx; + int i; + char *s; + + for(i = 0; i < numberof(ossl_sslctx_attrs); i++){ + char buf[32]; + snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]); + rb_iv_set(self, buf, Qnil); + } + if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){ + return self; + } + if(TYPE(ssl_method) == T_SYMBOL) + s = rb_id2name(SYM2ID(ssl_method)); + else + s = StringValuePtr(ssl_method); + for (i = 0; i < numberof(ossl_ssl_method_tab); i++) { + if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) { + method = ossl_ssl_method_tab[i].func(); + break; + } + } + if (!method) { + ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s); + } + Data_Get_Struct(self, SSL_CTX, ctx); + if (SSL_CTX_set_ssl_version(ctx, method) != 1) { + ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:"); + } + + return self; +} + +static VALUE +ossl_call_client_cert_cb(VALUE obj) +{ + VALUE cb, ary, cert, key; + SSL *ssl; + + Data_Get_Struct(obj, SSL, ssl); + cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx); + if (NIL_P(cb)) return Qfalse; + ary = rb_funcall(cb, rb_intern("call"), 1, obj); + Check_Type(ary, T_ARRAY); + GetX509CertPtr(cert = rb_ary_entry(ary, 0)); + GetPKeyPtr(key = rb_ary_entry(ary, 1)); + ossl_ssl_set_x509(obj, cert); + ossl_ssl_set_key(obj, key); + + return Qtrue; +} + +static int +ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) +{ + VALUE obj; + int status, success; + + obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb, + obj, &status); + if (status || !success) return 0; + *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj)); + *pkey = DupPKeyPtr(ossl_ssl_get_key(obj)); + + return 1; +} + +#if !defined(OPENSSL_NO_DH) +static VALUE +ossl_call_tmp_dh_callback(VALUE *args) +{ + SSL *ssl; + VALUE cb, dh; + EVP_PKEY *pkey; + + Data_Get_Struct(args[0], SSL, ssl); + cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx); + if (NIL_P(cb)) return Qfalse; + dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]); + pkey = GetPKeyPtr(dh); + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse; + ossl_ssl_set_tmp_dh(args[0], dh); + + return Qtrue; +} + +static DH* +ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) +{ + VALUE args[3]; + int status, success; + + args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + args[1] = INT2FIX(is_export); + args[2] = INT2FIX(keylength); + success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback, + (VALUE)args, &status); + if (status || !success) return NULL; + + return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh; +} + +static DH* +ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength) +{ + switch(keylength){ + case 512: + return OSSL_DEFAULT_DH_512; + case 1024: + return OSSL_DEFAULT_DH_1024; + } + return NULL; +} +#endif /* OPENSSL_NO_DH */ + +static int +ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) +{ + VALUE cb; + SSL *ssl; + + ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx); + X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb); + return ossl_verify_cb(preverify_ok, ctx); +} + +static VALUE +ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg) +{ + X509 *x509; + SSL_CTX *ctx; + + Data_Get_Struct(arg, SSL_CTX, ctx); + x509 = DupX509CertPtr(i); + if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){ + ossl_raise(eSSLError, NULL); + } + + return i; +} + +static VALUE +ossl_sslctx_setup(VALUE self) +{ + SSL_CTX *ctx; + X509 *cert = NULL, *client_ca = NULL; + X509_STORE *store; + EVP_PKEY *key = NULL; + char *ca_path = NULL, *ca_file = NULL; + int i, verify_mode; + VALUE val; + + if(OBJ_FROZEN(self)) return Qnil; + Data_Get_Struct(self, SSL_CTX, ctx); + +#if !defined(OPENSSL_NO_DH) + if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){ + SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); + } + else{ + rb_warning("using default DH parameters."); + SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback); + } +#endif + + val = ossl_sslctx_get_cert_store(self); + if(!NIL_P(val)){ + /* + * WORKAROUND: + * X509_STORE can count references, but + * X509_STORE_free() doesn't care it. + * So we won't increment it but mark it by ex_data. + */ + store = GetX509StorePtr(val); /* NO NEED TO DUP */ + SSL_CTX_set_cert_store(ctx, store); + SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); + } + + val = ossl_sslctx_get_extra_cert(self); + if(!NIL_P(val)){ + rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self); + } + + /* private key may be bundled in certificate file. */ + val = ossl_sslctx_get_cert(self); + cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */ + val = ossl_sslctx_get_key(self); + key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */ + if (cert && key) { + if (!SSL_CTX_use_certificate(ctx, cert)) { + /* Adds a ref => Safe to FREE */ + ossl_raise(eSSLError, "SSL_CTX_use_certificate:"); + } + if (!SSL_CTX_use_PrivateKey(ctx, key)) { + /* Adds a ref => Safe to FREE */ + ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:"); + } + if (!SSL_CTX_check_private_key(ctx)) { + ossl_raise(eSSLError, "SSL_CTX_check_private_key:"); + } + } + + val = ossl_sslctx_get_client_ca(self); + if(!NIL_P(val)){ + if(TYPE(val) == T_ARRAY){ + for(i = 0; i < RARRAY(val)->len; i++){ + client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]); + if (!SSL_CTX_add_client_CA(ctx, client_ca)){ + /* Copies X509_NAME => FREE it. */ + ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); + } + } + } + else{ + client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ + if (!SSL_CTX_add_client_CA(ctx, client_ca)){ + /* Copies X509_NAME => FREE it. */ + ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); + } + } + } + + val = ossl_sslctx_get_ca_file(self); + ca_file = NIL_P(val) ? NULL : StringValuePtr(val); + val = ossl_sslctx_get_ca_path(self); + ca_path = NIL_P(val) ? NULL : StringValuePtr(val); + if(ca_file || ca_path){ + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) + rb_warning("can't set verify locations"); + } + + val = ossl_sslctx_get_verify_mode(self); + verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); + SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback); + if (RTEST(ossl_sslctx_get_client_cert_cb(self))) + SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); + + val = ossl_sslctx_get_timeout(self); + if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val)); + + val = ossl_sslctx_get_verify_dep(self); + if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val)); + + val = ossl_sslctx_get_options(self); + if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val)); + rb_obj_freeze(self); + + val = ossl_sslctx_get_sess_id_ctx(self); + if (!NIL_P(val)){ + StringValue(val); + if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr, + RSTRING(val)->len)){ + ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:"); + } + } + + return Qtrue; +} + +static VALUE +ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher) +{ + VALUE ary; + int bits, alg_bits; + + ary = rb_ary_new2(4); + rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher))); + rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher))); + bits = SSL_CIPHER_get_bits(cipher, &alg_bits); + rb_ary_push(ary, INT2FIX(bits)); + rb_ary_push(ary, INT2FIX(alg_bits)); + + return ary; +} + +static VALUE +ossl_sslctx_get_ciphers(VALUE self) +{ + SSL_CTX *ctx; + STACK_OF(SSL_CIPHER) *ciphers; + SSL_CIPHER *cipher; + VALUE ary; + int i, num; + + Data_Get_Struct(self, SSL_CTX, ctx); + if(!ctx){ + rb_warning("SSL_CTX is not initialized."); + return Qnil; + } + ciphers = ctx->cipher_list; + + if (!ciphers) + return rb_ary_new(); + + num = sk_num((STACK*)ciphers); + ary = rb_ary_new2(num); + for(i = 0; i < num; i++){ + cipher = (SSL_CIPHER*)sk_value((STACK*)ciphers, i); + rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher)); + } + return ary; +} + +static VALUE +ossl_sslctx_set_ciphers(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + VALUE str, elem; + int i; + + rb_check_frozen(self); + if (NIL_P(v)) + return v; + else if (TYPE(v) == T_ARRAY) { + str = rb_str_new(0, 0); + for (i = 0; i < RARRAY(v)->len; i++) { + elem = rb_ary_entry(v, i); + if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0); + elem = rb_String(elem); + rb_str_append(str, elem); + if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":"); + } + } else { + str = v; + StringValue(str); + } + + Data_Get_Struct(self, SSL_CTX, ctx); + if(!ctx){ + ossl_raise(eSSLError, "SSL_CTX is not initialized."); + return Qnil; + } + if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) { + ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:"); + } + + return v; +} + +/* + * SSLSocket class + */ +static void +ossl_ssl_shutdown(SSL *ssl) +{ + if (ssl) { + SSL_shutdown(ssl); + SSL_clear(ssl); + } +} + +static void +ossl_ssl_free(SSL *ssl) +{ + ossl_ssl_shutdown(ssl); + SSL_free(ssl); +} + +static VALUE +ossl_ssl_s_alloc(VALUE klass) +{ + return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL); +} + +static VALUE +ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE io, ctx; + + if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) { + ctx = rb_funcall(cSSLContext, rb_intern("new"), 0); + } + OSSL_Check_Kind(ctx, cSSLContext); + Check_Type(io, T_FILE); + ossl_ssl_set_io(self, io); + ossl_ssl_set_ctx(self, ctx); + ossl_ssl_set_sync_close(self, Qfalse); + ossl_sslctx_setup(ctx); + rb_call_super(0, 0); + + return self; +} + +static VALUE +ossl_ssl_setup(VALUE self) +{ + VALUE io, v_ctx, cb; + SSL_CTX *ctx; + SSL *ssl; + OpenFile *fptr; + + Data_Get_Struct(self, SSL, ssl); + if(!ssl){ + v_ctx = ossl_ssl_get_ctx(self); + Data_Get_Struct(v_ctx, SSL_CTX, ctx); + + ssl = SSL_new(ctx); + if (!ssl) { + ossl_raise(eSSLError, "SSL_new:"); + } + DATA_PTR(self) = ssl; + + io = ossl_ssl_get_io(self); + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + rb_io_check_writable(fptr); + SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f))); + SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); + cb = ossl_sslctx_get_verify_cb(v_ctx); + SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); + cb = ossl_sslctx_get_client_cert_cb(v_ctx); + SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb); + cb = ossl_sslctx_get_tmp_dh_cb(v_ctx); + SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb); + } + + return Qtrue; +} + +#ifdef _WIN32 +#define ssl_get_error(ssl, ret) \ + (errno = WSAGetLastError(), SSL_get_error(ssl, ret)) +#else +#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret) +#endif + +static VALUE +ossl_start_ssl(VALUE self, int (*func)()) +{ + SSL *ssl; + OpenFile *fptr; + int ret; + + Data_Get_Struct(self, SSL, ssl); + GetOpenFile(ossl_ssl_get_io(self), fptr); + for(;;){ + if((ret = func(ssl)) > 0) break; + switch(ssl_get_error(ssl, ret)){ + case SSL_ERROR_WANT_WRITE: + rb_io_wait_writable(fileno(fptr->f)); + continue; + case SSL_ERROR_WANT_READ: + rb_io_wait_readable(fileno(fptr->f)); + continue; + case SSL_ERROR_SYSCALL: + if (errno) rb_sys_fail(0); + default: + ossl_raise(eSSLError, NULL); + } + } + + return self; +} + +static VALUE +ossl_ssl_connect(VALUE self) +{ + ossl_ssl_setup(self); + return ossl_start_ssl(self, SSL_connect); +} + +static VALUE +ossl_ssl_accept(VALUE self) +{ + ossl_ssl_setup(self); + return ossl_start_ssl(self, SSL_accept); +} + +static VALUE +ossl_ssl_read(int argc, VALUE *argv, VALUE self) +{ + SSL *ssl; + int ilen, nread = 0; + VALUE len, str; + OpenFile *fptr; + + rb_scan_args(argc, argv, "11", &len, &str); + ilen = NUM2INT(len); + if(NIL_P(str)) str = rb_str_new(0, ilen); + else{ + StringValue(str); + rb_str_modify(str); + rb_str_resize(str, ilen); + } + if(ilen == 0) return str; + + Data_Get_Struct(self, SSL, ssl); + GetOpenFile(ossl_ssl_get_io(self), fptr); + if (ssl) { + if(SSL_pending(ssl) <= 0) + rb_thread_wait_fd(fileno(fptr->f)); + for (;;){ + nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len); + switch(ssl_get_error(ssl, nread)){ + case SSL_ERROR_NONE: + goto end; + case SSL_ERROR_ZERO_RETURN: + rb_eof_error(); + case SSL_ERROR_WANT_WRITE: + rb_io_wait_writable(fileno(fptr->f)); + continue; + case SSL_ERROR_WANT_READ: + rb_io_wait_readable(fileno(fptr->f)); + continue; + case SSL_ERROR_SYSCALL: + if(ERR_peek_error() == 0 && nread == 0) rb_eof_error(); + rb_sys_fail(0); + default: + ossl_raise(eSSLError, "SSL_read:"); + } + } + } + else { + ID id_sysread = rb_intern("sysread"); + rb_warning("SSL session is not started yet."); + return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str); + } + + end: + RSTRING(str)->len = nread; + RSTRING(str)->ptr[nread] = 0; + OBJ_TAINT(str); + + return str; +} + +static VALUE +ossl_ssl_write(VALUE self, VALUE str) +{ + SSL *ssl; + int nwrite = 0; + OpenFile *fptr; + + StringValue(str); + Data_Get_Struct(self, SSL, ssl); + GetOpenFile(ossl_ssl_get_io(self), fptr); + + if (ssl) { + for (;;){ + nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len); + switch(ssl_get_error(ssl, nwrite)){ + case SSL_ERROR_NONE: + goto end; + case SSL_ERROR_WANT_WRITE: + rb_io_wait_writable(fileno(fptr->f)); + continue; + case SSL_ERROR_WANT_READ: + rb_io_wait_readable(fileno(fptr->f)); + continue; + case SSL_ERROR_SYSCALL: + if (errno) rb_sys_fail(0); + default: + ossl_raise(eSSLError, "SSL_write:"); + } + } + } + else { + ID id_syswrite = rb_intern("syswrite"); + rb_warning("SSL session is not started yet."); + return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str); + } + + end: + return INT2NUM(nwrite); +} + +static VALUE +ossl_ssl_close(VALUE self) +{ + SSL *ssl; + + Data_Get_Struct(self, SSL, ssl); + ossl_ssl_shutdown(ssl); + if (RTEST(ossl_ssl_get_sync_close(self))) + rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0); + + return Qnil; +} + +static VALUE +ossl_ssl_get_cert(VALUE self) +{ + SSL *ssl; + X509 *cert = NULL; + + Data_Get_Struct(self, SSL, ssl); + if (ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + + /* + * Is this OpenSSL bug? Should add a ref? + * TODO: Ask for. + */ + cert = SSL_get_certificate(ssl); /* NO DUPs => DON'T FREE. */ + + if (!cert) { + return Qnil; + } + return ossl_x509_new(cert); +} + +static VALUE +ossl_ssl_get_peer_cert(VALUE self) +{ + SSL *ssl; + X509 *cert = NULL; + VALUE obj; + + Data_Get_Struct(self, SSL, ssl); + + if (!ssl){ + rb_warning("SSL session is not started yet."); + return Qnil; + } + + cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */ + + if (!cert) { + return Qnil; + } + obj = ossl_x509_new(cert); + X509_free(cert); + + return obj; +} + +static VALUE +ossl_ssl_get_peer_cert_chain(VALUE self) +{ + SSL *ssl; + STACK_OF(X509) *chain; + X509 *cert; + VALUE ary; + int i, num; + + Data_Get_Struct(self, SSL, ssl); + if(!ssl){ + rb_warning("SSL session is not started yet."); + return Qnil; + } + chain = SSL_get_peer_cert_chain(ssl); + if(!chain) return Qnil; + num = sk_num(chain); + ary = rb_ary_new2(num); + for (i = 0; i < num; i++){ + cert = (X509*)sk_value(chain, i); + rb_ary_push(ary, ossl_x509_new(cert)); + } + + return ary; +} + +static VALUE +ossl_ssl_get_cipher(VALUE self) +{ + SSL *ssl; + SSL_CIPHER *cipher; + + Data_Get_Struct(self, SSL, ssl); + if (!ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + cipher = SSL_get_current_cipher(ssl); + + return ossl_ssl_cipher_to_ary(cipher); +} + +static VALUE +ossl_ssl_get_state(VALUE self) +{ + SSL *ssl; + VALUE ret; + + Data_Get_Struct(self, SSL, ssl); + if (!ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + ret = rb_str_new2(SSL_state_string(ssl)); + if (ruby_verbose) { + rb_str_cat2(ret, ": "); + rb_str_cat2(ret, SSL_state_string_long(ssl)); + } + return ret; +} + +static VALUE +ossl_ssl_pending(VALUE self) +{ + SSL *ssl; + + Data_Get_Struct(self, SSL, ssl); + if (!ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + + return INT2NUM(SSL_pending(ssl)); +} + +void +Init_ossl_ssl() +{ + int i; + + ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0); + ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0); + ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0); + ossl_ssl_ex_client_cert_cb_idx = + SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0); + ossl_ssl_ex_tmp_dh_callback_idx = + SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0); + + mSSL = rb_define_module_under(mOSSL, "SSL"); + eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError); + + /* class SSLContext */ + cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject); + rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc); + for(i = 0; i < numberof(ossl_sslctx_attrs); i++) + rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse); + rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1); + rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); + rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); + + /* class SSLSocket */ + cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject); + rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc); + for(i = 0; i < numberof(ossl_ssl_attr_readers); i++) + rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse); + for(i = 0; i < numberof(ossl_ssl_attrs); i++) + rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse); + rb_define_alias(cSSLSocket, "to_io", "io"); + rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1); + rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0); + rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0); + rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1); + rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1); + rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0); + rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0); + rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0); + rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0); + rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0); + rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0); + rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0); + +#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x)) + + ossl_ssl_def_const(VERIFY_NONE); + ossl_ssl_def_const(VERIFY_PEER); + ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT); + ossl_ssl_def_const(VERIFY_CLIENT_ONCE); + /* Not introduce constants included in OP_ALL such as... + * ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG); + * ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG); + * ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); + * ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG); + * ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER); + * ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING); + * ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG); + * ossl_ssl_def_const(OP_TLS_D5_BUG); + * ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG); + * ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS); + */ + ossl_ssl_def_const(OP_ALL); +#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) + ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); +#endif +#if defined(SSL_OP_SINGLE_ECDH_USE) + ossl_ssl_def_const(OP_SINGLE_ECDH_USE); +#endif + ossl_ssl_def_const(OP_SINGLE_DH_USE); + ossl_ssl_def_const(OP_EPHEMERAL_RSA); +#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) + ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE); +#endif + ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG); + ossl_ssl_def_const(OP_NO_SSLv2); + ossl_ssl_def_const(OP_NO_SSLv3); + ossl_ssl_def_const(OP_NO_TLSv1); + ossl_ssl_def_const(OP_PKCS1_CHECK_1); + ossl_ssl_def_const(OP_PKCS1_CHECK_2); + ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG); + ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_ssl.h b/ruby_1_8_5/ext/openssl/ossl_ssl.h new file mode 100644 index 0000000000..ba9ddb1985 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_ssl.h @@ -0,0 +1,21 @@ +/* + * $Id: ossl_ssl.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_SSL_H_) +#define _OSSL_SSL_H_ + +extern VALUE mSSL; +extern VALUE eSSLError; +extern VALUE cSSLSocket; +extern VALUE cSSLContext; + +void Init_ossl_ssl(void); + +#endif /* _OSSL_SSL_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_version.h b/ruby_1_8_5/ext/openssl/ossl_version.h new file mode 100644 index 0000000000..6d43cdccbf --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_version.h @@ -0,0 +1,16 @@ +/* + * $Id: ossl_version.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_VERSION_H_) +#define _OSSL_VERSION_H_ + +#define OSSL_VERSION "1.0.0" + +#endif /* _OSSL_VERSION_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_x509.c b/ruby_1_8_5/ext/openssl/ossl_x509.c new file mode 100644 index 0000000000..fa90e92d11 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509.c @@ -0,0 +1,104 @@ +/* + * $Id: ossl_x509.c,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +VALUE mX509; + +#define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x)) +#define DefX509Default(x,i) \ + rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i())) + +void +Init_ossl_x509() +{ + mX509 = rb_define_module_under(mOSSL, "X509"); + + Init_ossl_x509attr(); + Init_ossl_x509cert(); + Init_ossl_x509crl(); + Init_ossl_x509ext(); + Init_ossl_x509name(); + Init_ossl_x509req(); + Init_ossl_x509revoked(); + Init_ossl_x509store(); + + DefX509Const(V_OK); + DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT); + DefX509Const(V_ERR_UNABLE_TO_GET_CRL); + DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); + DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE); + DefX509Const(V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); + DefX509Const(V_ERR_CERT_SIGNATURE_FAILURE); + DefX509Const(V_ERR_CRL_SIGNATURE_FAILURE); + DefX509Const(V_ERR_CERT_NOT_YET_VALID); + DefX509Const(V_ERR_CERT_HAS_EXPIRED); + DefX509Const(V_ERR_CRL_NOT_YET_VALID); + DefX509Const(V_ERR_CRL_HAS_EXPIRED); + DefX509Const(V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD); + DefX509Const(V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD); + DefX509Const(V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); + DefX509Const(V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); + DefX509Const(V_ERR_OUT_OF_MEM); + DefX509Const(V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); + DefX509Const(V_ERR_SELF_SIGNED_CERT_IN_CHAIN); + DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); + DefX509Const(V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); + DefX509Const(V_ERR_CERT_CHAIN_TOO_LONG); + DefX509Const(V_ERR_CERT_REVOKED); + DefX509Const(V_ERR_INVALID_CA); + DefX509Const(V_ERR_PATH_LENGTH_EXCEEDED); + DefX509Const(V_ERR_INVALID_PURPOSE); + DefX509Const(V_ERR_CERT_UNTRUSTED); + DefX509Const(V_ERR_CERT_REJECTED); + DefX509Const(V_ERR_SUBJECT_ISSUER_MISMATCH); + DefX509Const(V_ERR_AKID_SKID_MISMATCH); + DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH); + DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN); + DefX509Const(V_ERR_APPLICATION_VERIFICATION); + +#if defined(X509_V_FLAG_CRL_CHECK) + DefX509Const(V_FLAG_CRL_CHECK); +#endif +#if defined(X509_V_FLAG_CRL_CHECK_ALL) + DefX509Const(V_FLAG_CRL_CHECK_ALL); +#endif + + DefX509Const(PURPOSE_SSL_CLIENT); + DefX509Const(PURPOSE_SSL_SERVER); + DefX509Const(PURPOSE_NS_SSL_SERVER); + DefX509Const(PURPOSE_SMIME_SIGN); + DefX509Const(PURPOSE_SMIME_ENCRYPT); + DefX509Const(PURPOSE_CRL_SIGN); + DefX509Const(PURPOSE_ANY); +#if defined(X509_PURPOSE_OCSP_HELPER) + DefX509Const(PURPOSE_OCSP_HELPER); +#endif + + DefX509Const(TRUST_COMPAT); + DefX509Const(TRUST_SSL_CLIENT); + DefX509Const(TRUST_SSL_SERVER); + DefX509Const(TRUST_EMAIL); + DefX509Const(TRUST_OBJECT_SIGN); +#if defined(X509_TRUST_OCSP_SIGN) + DefX509Const(TRUST_OCSP_SIGN); +#endif +#if defined(X509_TRUST_OCSP_REQUEST) + DefX509Const(TRUST_OCSP_REQUEST); +#endif + + DefX509Default(CERT_AREA, cert_area); + DefX509Default(CERT_DIR, cert_dir); + DefX509Default(CERT_FILE, cert_file); + DefX509Default(CERT_DIR_ENV, cert_dir_env); + DefX509Default(CERT_FILE_ENV, cert_file_env); + DefX509Default(PRIVATE_DIR, private_dir); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_x509.h b/ruby_1_8_5/ext/openssl/ossl_x509.h new file mode 100644 index 0000000000..8d1f77b302 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509.h @@ -0,0 +1,114 @@ +/* + * $Id: ossl_x509.h,v 1.2 2003/11/01 09:24:55 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_X509_H_) +#define _OSSL_X509_H_ + +/* + * X509 main module + */ +extern VALUE mX509; + +void Init_ossl_x509(void); + +/* + * X509Attr + */ +extern VALUE cX509Attr; +extern VALUE eX509AttrError; + +VALUE ossl_x509attr_new(X509_ATTRIBUTE *); +X509_ATTRIBUTE *DupX509AttrPtr(VALUE); +void Init_ossl_x509attr(void); + +/* + * X509Cert + */ +extern VALUE cX509Cert; +extern VALUE eX509CertError; + +VALUE ossl_x509_new(X509 *); +VALUE ossl_x509_new_from_file(VALUE); +X509 *GetX509CertPtr(VALUE); +X509 *DupX509CertPtr(VALUE); +void Init_ossl_x509cert(void); + +/* + * X509CRL + */ +extern VALUE cX509CRL; +extern VALUE eX509CRLError; + +VALUE ossl_x509crl_new(X509_CRL *); +X509_CRL *GetX509CRLPtr(VALUE); +X509_CRL *DupX509CRLPtr(VALUE); +void Init_ossl_x509crl(void); + +/* + * X509Extension + */ +extern VALUE cX509Ext; +extern VALUE cX509ExtFactory; +extern VALUE eX509ExtError; + +VALUE ossl_x509ext_new(X509_EXTENSION *); +X509_EXTENSION *GetX509ExtPtr(VALUE); +X509_EXTENSION *DupX509ExtPtr(VALUE); +void Init_ossl_x509ext(void); + +/* + * X509Name + */ +extern VALUE cX509Name; +extern VALUE eX509NameError; + +VALUE ossl_x509name_new(X509_NAME *); +X509_NAME *GetX509NamePtr(VALUE); +void Init_ossl_x509name(void); + +/* + * X509Request + */ +extern VALUE cX509Req; +extern VALUE eX509ReqError; + +VALUE ossl_x509req_new(X509_REQ *); +X509_REQ *GetX509ReqPtr(VALUE); +X509_REQ *DupX509ReqPtr(VALUE); +void Init_ossl_x509req(void); + +/* + * X509Revoked + */ +extern VALUE cX509Rev; +extern VALUE eX509RevError; + +VALUE ossl_x509revoked_new(X509_REVOKED *); +X509_REVOKED *DupX509RevokedPtr(VALUE); +void Init_ossl_x509revoked(void); + +/* + * X509Store and X509StoreContext + */ +extern VALUE cX509Store; +extern VALUE cX509StoreContext; +extern VALUE eX509StoreError; + +VALUE ossl_x509store_new(X509_STORE *); +X509_STORE *GetX509StorePtr(VALUE); +X509_STORE *DupX509StorePtr(VALUE); + +VALUE ossl_x509stctx_new(X509_STORE_CTX *); +VALUE ossl_x509stctx_clear_ptr(VALUE); +X509_STORE_CTX *GetX509StCtxtPtr(VALUE); + +void Init_ossl_x509store(void); + +#endif /* _OSSL_X509_H_ */ diff --git a/ruby_1_8_5/ext/openssl/ossl_x509attr.c b/ruby_1_8_5/ext/openssl/ossl_x509attr.c new file mode 100644 index 0000000000..91a0795209 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509attr.c @@ -0,0 +1,249 @@ +/* + * $Id: ossl_x509attr.c,v 1.4.2.2 2004/12/15 01:54:38 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509Attr(klass, obj, attr) do { \ + if (!attr) { \ + ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \ +} while (0) +#define GetX509Attr(obj, attr) do { \ + Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \ + if (!attr) { \ + ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509Attr(obj, attr) do { \ + OSSL_Check_Kind(obj, cX509Attr); \ + GetX509Attr(obj, attr); \ +} while (0) + +/* + * Classes + */ +VALUE cX509Attr; +VALUE eX509AttrError; + +/* + * Public + */ +VALUE +ossl_x509attr_new(X509_ATTRIBUTE *attr) +{ + X509_ATTRIBUTE *new; + VALUE obj; + + if (!attr) { + new = X509_ATTRIBUTE_new(); + } else { + new = X509_ATTRIBUTE_dup(attr); + } + if (!new) { + ossl_raise(eX509AttrError, NULL); + } + WrapX509Attr(cX509Attr, obj, new); + + return obj; +} + +X509_ATTRIBUTE * +DupX509AttrPtr(VALUE obj) +{ + X509_ATTRIBUTE *attr, *new; + + SafeGetX509Attr(obj, attr); + if (!(new = X509_ATTRIBUTE_dup(attr))) { + ossl_raise(eX509AttrError, NULL); + } + + return new; +} + +/* + * Private + */ +static VALUE +ossl_x509attr_alloc(VALUE klass) +{ + X509_ATTRIBUTE *attr; + VALUE obj; + + if (!(attr = X509_ATTRIBUTE_new())) + ossl_raise(eX509AttrError, NULL); + WrapX509Attr(klass, obj, attr); + + return obj; +} + +static VALUE +ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE oid, value; + X509_ATTRIBUTE *attr; + unsigned char *p; + + GetX509Attr(self, attr); + if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){ + oid = ossl_to_der_if_possible(oid); + StringValue(oid); + p = RSTRING(oid)->ptr; + if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self), + &p, RSTRING(oid)->len)){ + ossl_raise(eX509AttrError, NULL); + } + return self; + } + rb_funcall(self, rb_intern("oid="), 1, oid); + rb_funcall(self, rb_intern("value="), 1, value); + + return self; +} + +static VALUE +ossl_x509attr_set_oid(VALUE self, VALUE oid) +{ + X509_ATTRIBUTE *attr; + ASN1_OBJECT *obj; + char *s; + + s = StringValuePtr(oid); + obj = OBJ_txt2obj(s, 0); + if(!obj) obj = OBJ_txt2obj(s, 1); + if(!obj) ossl_raise(eX509AttrError, NULL); + GetX509Attr(self, attr); + X509_ATTRIBUTE_set1_object(attr, obj); + + return oid; +} + +static VALUE +ossl_x509attr_get_oid(VALUE self) +{ + X509_ATTRIBUTE *attr; + ASN1_OBJECT *oid; + BIO *out; + VALUE ret; + int nid; + + GetX509Attr(self, attr); + oid = X509_ATTRIBUTE_get0_object(attr); + if ((nid = OBJ_obj2nid(oid)) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); + else{ + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509AttrError, NULL); + i2a_ASN1_OBJECT(out, oid); + ret = ossl_membio2str(out); + } + + return ret; +} + +#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE) +# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single) +# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1) +#else +# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->set) +# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0) +#endif + +static VALUE +ossl_x509attr_set_value(VALUE self, VALUE value) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *a1type; + + if(!(a1type = ossl_asn1_get_asn1type(value))) + ossl_raise(eASN1Error, "could not get ASN1_TYPE"); + if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){ + ASN1_TYPE_free(a1type); + ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value."); + } + GetX509Attr(self, attr); + if(attr->value.set){ + if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single); + else sk_ASN1_TYPE_free(attr->value.set); + } + OSSL_X509ATTR_SET_SINGLE(attr); + attr->value.single = a1type; + + return value; +} + +static VALUE +ossl_x509attr_get_value(VALUE self) +{ + X509_ATTRIBUTE *attr; + VALUE str, asn1; + long length; + unsigned char *p; + + GetX509Attr(self, attr); + if(attr->value.ptr == NULL) return Qnil; + if(OSSL_X509ATTR_IS_SINGLE(attr)){ + length = i2d_ASN1_TYPE(attr->value.single, NULL); + str = rb_str_new(0, length); + p = RSTRING(str)->ptr; + i2d_ASN1_TYPE(attr->value.single, &p); + ossl_str_adjust(str, p); + } + else{ + length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL, + i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0); + str = rb_str_new(0, length); + p = RSTRING(str)->ptr; + i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p, + i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0); + ossl_str_adjust(str, p); + } + asn1 = rb_funcall(mASN1, rb_intern("decode"), 1, str); + + return asn1; +} + +static VALUE +ossl_x509attr_to_der(VALUE self) +{ + X509_ATTRIBUTE *attr; + VALUE str; + int len; + unsigned char *p; + + GetX509Attr(self, attr); + if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0) + ossl_raise(eX509AttrError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_ATTRIBUTE(attr, &p) <= 0) + ossl_raise(eX509AttrError, NULL); + RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr; + + return str; +} + +/* + * X509_ATTRIBUTE init + */ +void +Init_ossl_x509attr() +{ + eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError); + + cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject); + rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc); + rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1); + rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1); + rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0); + rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1); + rb_define_method(cX509Attr, "value", ossl_x509attr_get_value, 0); + rb_define_method(cX509Attr, "to_der", ossl_x509attr_to_der, 0); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_x509cert.c b/ruby_1_8_5/ext/openssl/ossl_x509cert.c new file mode 100644 index 0000000000..3ac9c894da --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509cert.c @@ -0,0 +1,671 @@ +/* + * $Id: ossl_x509cert.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509(klass, obj, x509) do { \ + if (!x509) { \ + ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_free, x509); \ +} while (0) +#define GetX509(obj, x509) do { \ + Data_Get_Struct(obj, X509, x509); \ + if (!x509) { \ + ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509(obj, x509) do { \ + OSSL_Check_Kind(obj, cX509Cert); \ + GetX509(obj, x509); \ +} while (0) + +/* + * Classes + */ +VALUE cX509Cert; +VALUE eX509CertError; + +/* + * Public + */ +VALUE +ossl_x509_new(X509 *x509) +{ + X509 *new; + VALUE obj; + + if (!x509) { + new = X509_new(); + } else { + new = X509_dup(x509); + } + if (!new) { + ossl_raise(eX509CertError, NULL); + } + WrapX509(cX509Cert, obj, new); + + return obj; +} + +VALUE +ossl_x509_new_from_file(VALUE filename) +{ + X509 *x509; + FILE *fp; + VALUE obj; + + SafeStringValue(filename); + if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) { + ossl_raise(eX509CertError, "%s", strerror(errno)); + } + x509 = PEM_read_X509(fp, NULL, NULL, NULL); + /* + * prepare for DER... +#if !defined(OPENSSL_NO_FP_API) + if (!x509) { + rewind(fp); + + x509 = d2i_X509_fp(fp, NULL); + } +#endif + */ + fclose(fp); + if (!x509) { + ossl_raise(eX509CertError, NULL); + } + WrapX509(cX509Cert, obj, x509); + + return obj; +} + +X509 * +GetX509CertPtr(VALUE obj) +{ + X509 *x509; + + SafeGetX509(obj, x509); + + return x509; +} + +X509 * +DupX509CertPtr(VALUE obj) +{ + X509 *x509; + + SafeGetX509(obj, x509); + + CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); + + return x509; +} + +/* + * Private + */ +static VALUE +ossl_x509_alloc(VALUE klass) +{ + X509 *x509; + VALUE obj; + + x509 = X509_new(); + if (!x509) ossl_raise(eX509CertError, NULL); + + WrapX509(klass, obj, x509); + + return obj; +} + +static VALUE +ossl_x509_initialize(int argc, VALUE *argv, VALUE self) +{ + BIO *in; + X509 *x509; + VALUE arg; + + if (rb_scan_args(argc, argv, "01", &arg) == 0) { + /* create just empty X509Cert */ + return self; + } + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + x509 = PEM_read_bio_X509(in, (X509 **)&DATA_PTR(self), NULL, NULL); + if (!x509) { + BIO_reset(in); + x509 = d2i_X509_bio(in, (X509 **)&DATA_PTR(self)); + } + BIO_free(in); + if (!x509) ossl_raise(eX509CertError, NULL); + + return self; +} + +static VALUE +ossl_x509_copy(VALUE self, VALUE other) +{ + X509 *a, *b, *x509; + + rb_check_frozen(self); + if (self == other) return self; + + GetX509(self, a); + SafeGetX509(other, b); + + x509 = X509_dup(b); + if (!x509) ossl_raise(eX509CertError, NULL); + + DATA_PTR(self) = x509; + X509_free(a); + + return self; +} + +static VALUE +ossl_x509_to_der(VALUE self) +{ + X509 *x509; + VALUE str; + long len; + unsigned char *p; + + GetX509(self, x509); + if ((len = i2d_X509(x509, NULL)) <= 0) + ossl_raise(eX509CertError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if (i2d_X509(x509, &p) <= 0) + ossl_raise(eX509CertError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +static VALUE +ossl_x509_to_pem(VALUE self) +{ + X509 *x509; + BIO *out; + VALUE str; + + GetX509(self, x509); + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eX509CertError, NULL); + + if (!PEM_write_bio_X509(out, x509)) { + BIO_free(out); + ossl_raise(eX509CertError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_x509_to_text(VALUE self) +{ + X509 *x509; + BIO *out; + VALUE str; + + GetX509(self, x509); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eX509CertError, NULL); + + if (!X509_print(out, x509)) { + BIO_free(out); + ossl_raise(eX509CertError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +#if 0 +/* + * Makes from X509 X509_REQuest + */ +static VALUE +ossl_x509_to_req(VALUE self) +{ + X509 *x509; + X509_REQ *req; + VALUE obj; + + GetX509(self, x509); + if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) { + ossl_raise(eX509CertError, NULL); + } + obj = ossl_x509req_new(req); + X509_REQ_free(req); + + return obj; +} +#endif + +static VALUE +ossl_x509_get_version(VALUE self) +{ + X509 *x509; + + GetX509(self, x509); + + return LONG2NUM(X509_get_version(x509)); +} + +static VALUE +ossl_x509_set_version(VALUE self, VALUE version) +{ + X509 *x509; + long ver; + + if ((ver = NUM2LONG(version)) < 0) { + ossl_raise(eX509CertError, "version must be >= 0!"); + } + GetX509(self, x509); + if (!X509_set_version(x509, ver)) { + ossl_raise(eX509CertError, NULL); + } + + return version; +} + +static VALUE +ossl_x509_get_serial(VALUE self) +{ + X509 *x509; + + GetX509(self, x509); + + return asn1integer_to_num(X509_get_serialNumber(x509)); +} + +static VALUE +ossl_x509_set_serial(VALUE self, VALUE num) +{ + X509 *x509; + + GetX509(self, x509); + + x509->cert_info->serialNumber = + num_to_asn1integer(num, X509_get_serialNumber(x509)); + + return num; +} + +static VALUE +ossl_x509_get_signature_algorithm(VALUE self) +{ + X509 *x509; + BIO *out; + VALUE str; + + GetX509(self, x509); + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eX509CertError, NULL); + + if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) { + BIO_free(out); + ossl_raise(eX509CertError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_x509_get_subject(VALUE self) +{ + X509 *x509; + X509_NAME *name; + + GetX509(self, x509); + if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */ + ossl_raise(eX509CertError, NULL); + } + + return ossl_x509name_new(name); +} + +static VALUE +ossl_x509_set_subject(VALUE self, VALUE subject) +{ + X509 *x509; + + GetX509(self, x509); + if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */ + ossl_raise(eX509CertError, NULL); + } + + return subject; +} + +static VALUE +ossl_x509_get_issuer(VALUE self) +{ + X509 *x509; + X509_NAME *name; + + GetX509(self, x509); + if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */ + ossl_raise(eX509CertError, NULL); + } + + return ossl_x509name_new(name); +} + +static VALUE +ossl_x509_set_issuer(VALUE self, VALUE issuer) +{ + X509 *x509; + + GetX509(self, x509); + if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */ + ossl_raise(eX509CertError, NULL); + } + + return issuer; +} + +static VALUE +ossl_x509_get_not_before(VALUE self) +{ + X509 *x509; + ASN1_UTCTIME *asn1time; + + GetX509(self, x509); + if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */ + ossl_raise(eX509CertError, NULL); + } + + return asn1time_to_time(asn1time); +} + +static VALUE +ossl_x509_set_not_before(VALUE self, VALUE time) +{ + X509 *x509; + time_t sec; + + sec = time_to_time_t(time); + GetX509(self, x509); + if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) { + ossl_raise(eX509CertError, NULL); + } + + return time; +} + +static VALUE +ossl_x509_get_not_after(VALUE self) +{ + X509 *x509; + ASN1_TIME *asn1time; + + GetX509(self, x509); + if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */ + ossl_raise(eX509CertError, NULL); + } + + return asn1time_to_time(asn1time); +} + +static VALUE +ossl_x509_set_not_after(VALUE self, VALUE time) +{ + X509 *x509; + time_t sec; + + sec = time_to_time_t(time); + GetX509(self, x509); + if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) { + ossl_raise(eX509CertError, NULL); + } + + return time; +} + +static VALUE +ossl_x509_get_public_key(VALUE self) +{ + X509 *x509; + EVP_PKEY *pkey; + + GetX509(self, x509); + if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */ + ossl_raise(eX509CertError, NULL); + } + + return ossl_pkey_new(pkey); /* NO DUP - OK */ +} + +static VALUE +ossl_x509_set_public_key(VALUE self, VALUE key) +{ + X509 *x509; + + GetX509(self, x509); + if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */ + ossl_raise(eX509CertError, NULL); + } + + return key; +} + +static VALUE +ossl_x509_sign(VALUE self, VALUE key, VALUE digest) +{ + X509 *x509; + EVP_PKEY *pkey; + const EVP_MD *md; + + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + md = GetDigestPtr(digest); + GetX509(self, x509); + if (!X509_sign(x509, pkey, md)) { + ossl_raise(eX509CertError, NULL); + } + + return self; +} + +/* + * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' + */ +static VALUE +ossl_x509_verify(VALUE self, VALUE key) +{ + X509 *x509; + EVP_PKEY *pkey; + int i; + + pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ + GetX509(self, x509); + if ((i = X509_verify(x509, pkey)) < 0) { + ossl_raise(eX509CertError, NULL); + } + if (i > 0) { + return Qtrue; + } + + return Qfalse; +} + +/* + * Checks if 'key' is PRIV key for this cert + */ +static VALUE +ossl_x509_check_private_key(VALUE self, VALUE key) +{ + X509 *x509; + EVP_PKEY *pkey; + + /* not needed private key, but should be */ + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + GetX509(self, x509); + if (!X509_check_private_key(x509, pkey)) { + OSSL_Warning("Check private key:%s", OSSL_ErrMsg()); + return Qfalse; + } + + return Qtrue; +} + +/* + * Gets X509v3 extensions as array of X509Ext objects + */ +static VALUE +ossl_x509_get_extensions(VALUE self) +{ + X509 *x509; + int count, i; + X509_EXTENSION *ext; + VALUE ary; + + GetX509(self, x509); + count = X509_get_ext_count(x509); + if (count < 0) { + return rb_ary_new(); + } + ary = rb_ary_new2(count); + for (i=0; ilen; i++) { + OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext); + } + GetX509(self, x509); + sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free); + x509->cert_info->extensions = NULL; + for (i=0; ilen; i++) { + ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]); + + if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); + ossl_raise(eX509CertError, NULL); + } + X509_EXTENSION_free(ext); + } + + return ary; +} + +static VALUE +ossl_x509_add_extension(VALUE self, VALUE extension) +{ + X509 *x509; + X509_EXTENSION *ext; + + GetX509(self, x509); + ext = DupX509ExtPtr(extension); + if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); + ossl_raise(eX509CertError, NULL); + } + X509_EXTENSION_free(ext); + + return extension; +} + +static VALUE +ossl_x509_inspect(VALUE self) +{ + VALUE str; + char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new2("#<"); + rb_str_cat2(str, cname); + rb_str_cat2(str, " "); + + rb_str_cat2(str, "subject="); + rb_str_append(str, rb_inspect(ossl_x509_get_subject(self))); + rb_str_cat2(str, ", "); + + rb_str_cat2(str, "issuer="); + rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self))); + rb_str_cat2(str, ", "); + + rb_str_cat2(str, "serial="); + rb_str_append(str, rb_inspect(ossl_x509_get_serial(self))); + rb_str_cat2(str, ", "); + + rb_str_cat2(str, "not_before="); + rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self))); + rb_str_cat2(str, ", "); + + rb_str_cat2(str, "not_after="); + rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self))); + + str = rb_str_cat2(str, ">"); + + return str; +} + +/* + * INIT + */ +void +Init_ossl_x509cert() +{ + eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError); + + cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject); + + rb_define_alloc_func(cX509Cert, ossl_x509_alloc); + rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1); + rb_define_copy_func(cX509Cert, ossl_x509_copy); + + rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0); + rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0); + rb_define_alias(cX509Cert, "to_s", "to_pem"); + rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0); + rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0); + rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1); + rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0); + rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0); + rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1); + rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0); + rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1); + rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0); + rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1); + rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0); + rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1); + rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0); + rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1); + rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0); + rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1); + rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2); + rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1); + rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1); + rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0); + rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1); + rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1); + rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_x509crl.c b/ruby_1_8_5/ext/openssl/ossl_x509crl.c new file mode 100644 index 0000000000..62d27fe7a4 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509crl.c @@ -0,0 +1,535 @@ +/* + * $Id: ossl_x509crl.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509CRL(klass, obj, crl) do { \ + if (!crl) { \ + ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_CRL_free, crl); \ +} while (0) +#define GetX509CRL(obj, crl) do { \ + Data_Get_Struct(obj, X509_CRL, crl); \ + if (!crl) { \ + ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509CRL(obj, crl) do { \ + OSSL_Check_Kind(obj, cX509CRL); \ + GetX509CRL(obj, crl); \ +} while (0) + +/* + * Classes + */ +VALUE cX509CRL; +VALUE eX509CRLError; + +/* + * PUBLIC + */ +X509_CRL * +GetX509CRLPtr(VALUE obj) +{ + X509_CRL *crl; + + SafeGetX509CRL(obj, crl); + + return crl; +} + +X509_CRL * +DupX509CRLPtr(VALUE obj) +{ + X509_CRL *crl; + + SafeGetX509CRL(obj, crl); + CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); + + return crl; +} + +VALUE +ossl_x509crl_new(X509_CRL *crl) +{ + X509_CRL *tmp; + VALUE obj; + + tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new(); + if(!tmp) ossl_raise(eX509CRLError, NULL); + WrapX509CRL(cX509CRL, obj, tmp); + + return obj; +} + +/* + * PRIVATE + */ +static VALUE +ossl_x509crl_alloc(VALUE klass) +{ + X509_CRL *crl; + VALUE obj; + + if (!(crl = X509_CRL_new())) { + ossl_raise(eX509CRLError, NULL); + } + WrapX509CRL(klass, obj, crl); + + return obj; +} + +static VALUE +ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) +{ + BIO *in; + X509_CRL *crl; + VALUE arg; + + if (rb_scan_args(argc, argv, "01", &arg) == 0) { + return self; + } + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + crl = PEM_read_bio_X509_CRL(in, (X509_CRL **)&DATA_PTR(self), NULL, NULL); + if (!crl) { + BIO_reset(in); + crl = d2i_X509_CRL_bio(in, (X509_CRL **)&DATA_PTR(self)); + } + BIO_free(in); + if (!crl) ossl_raise(eX509CRLError, NULL); + + return self; +} + +static VALUE +ossl_x509crl_copy(VALUE self, VALUE other) +{ + X509_CRL *a, *b, *crl; + + rb_check_frozen(self); + if (self == other) return self; + GetX509CRL(self, a); + SafeGetX509CRL(other, b); + if (!(crl = X509_CRL_dup(b))) { + ossl_raise(eX509CRLError, NULL); + } + X509_CRL_free(a); + DATA_PTR(self) = crl; + + return self; +} + +static VALUE +ossl_x509crl_get_version(VALUE self) +{ + X509_CRL *crl; + long ver; + + GetX509CRL(self, crl); + ver = X509_CRL_get_version(crl); + + return LONG2NUM(ver); +} + +static VALUE +ossl_x509crl_set_version(VALUE self, VALUE version) +{ + X509_CRL *crl; + long ver; + + if ((ver = NUM2LONG(version)) < 0) { + ossl_raise(eX509CRLError, "version must be >= 0!"); + } + GetX509CRL(self, crl); + if (!X509_CRL_set_version(crl, ver)) { + ossl_raise(eX509CRLError, NULL); + } + + return version; +} + +static VALUE +ossl_x509crl_get_signature_algorithm(VALUE self) +{ + X509_CRL *crl; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509CRL(self, crl); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509CRLError, NULL); + } + if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) { + BIO_free(out); + ossl_raise(eX509CRLError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + return str; +} + +static VALUE +ossl_x509crl_get_issuer(VALUE self) +{ + X509_CRL *crl; + + GetX509CRL(self, crl); + + return ossl_x509name_new(X509_CRL_get_issuer(crl)); /* NO DUP - don't free */ +} + +static VALUE +ossl_x509crl_set_issuer(VALUE self, VALUE issuer) +{ + X509_CRL *crl; + + GetX509CRL(self, crl); + + if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */ + ossl_raise(eX509CRLError, NULL); + } + return issuer; +} + +static VALUE +ossl_x509crl_get_last_update(VALUE self) +{ + X509_CRL *crl; + + GetX509CRL(self, crl); + + return asn1time_to_time(X509_CRL_get_lastUpdate(crl)); +} + +static VALUE +ossl_x509crl_set_last_update(VALUE self, VALUE time) +{ + X509_CRL *crl; + time_t sec; + + sec = time_to_time_t(time); + GetX509CRL(self, crl); + if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) { + ossl_raise(eX509CRLError, NULL); + } + + return time; +} + +static VALUE +ossl_x509crl_get_next_update(VALUE self) +{ + X509_CRL *crl; + + GetX509CRL(self, crl); + + return asn1time_to_time(X509_CRL_get_nextUpdate(crl)); +} + +static VALUE +ossl_x509crl_set_next_update(VALUE self, VALUE time) +{ + X509_CRL *crl; + time_t sec; + + sec = time_to_time_t(time); + GetX509CRL(self, crl); + /* This must be some thinko in OpenSSL */ + if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){ + ossl_raise(eX509CRLError, NULL); + } + + return time; +} + +static VALUE +ossl_x509crl_get_revoked(VALUE self) +{ + X509_CRL *crl; + int i, num; + X509_REVOKED *rev; + VALUE ary, revoked; + + GetX509CRL(self, crl); + num = sk_X509_CRL_num(X509_CRL_get_REVOKED(crl)); + if (num < 0) { + OSSL_Debug("num < 0???"); + return rb_ary_new(); + } + ary = rb_ary_new2(num); + for(i=0; ilen; i++) { + OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev); + } + GetX509CRL(self, crl); + sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free); + crl->crl->revoked = NULL; + for (i=0; ilen; i++) { + rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]); + if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ + ossl_raise(eX509CRLError, NULL); + } + } + X509_CRL_sort(crl); + + return ary; +} + +static VALUE +ossl_x509crl_add_revoked(VALUE self, VALUE revoked) +{ + X509_CRL *crl; + X509_REVOKED *rev; + + GetX509CRL(self, crl); + rev = DupX509RevokedPtr(revoked); + if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ + ossl_raise(eX509CRLError, NULL); + } + X509_CRL_sort(crl); + + return revoked; +} + +static VALUE +ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest) +{ + X509_CRL *crl; + EVP_PKEY *pkey; + const EVP_MD *md; + + GetX509CRL(self, crl); + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + md = GetDigestPtr(digest); + if (!X509_CRL_sign(crl, pkey, md)) { + ossl_raise(eX509CRLError, NULL); + } + + return self; +} + +static VALUE +ossl_x509crl_verify(VALUE self, VALUE key) +{ + X509_CRL *crl; + int ret; + + GetX509CRL(self, crl); + if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) { + ossl_raise(eX509CRLError, NULL); + } + if (ret == 1) { + return Qtrue; + } + + return Qfalse; +} + +static VALUE +ossl_x509crl_to_der(VALUE self) +{ + X509_CRL *crl; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509CRL(self, crl); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509CRLError, NULL); + } + if (!i2d_X509_CRL_bio(out, crl)) { + BIO_free(out); + ossl_raise(eX509CRLError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +static VALUE +ossl_x509crl_to_pem(VALUE self) +{ + X509_CRL *crl; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509CRL(self, crl); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509CRLError, NULL); + } + if (!PEM_write_bio_X509_CRL(out, crl)) { + BIO_free(out); + ossl_raise(eX509CRLError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +static VALUE +ossl_x509crl_to_text(VALUE self) +{ + X509_CRL *crl; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509CRL(self, crl); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509CRLError, NULL); + } + if (!X509_CRL_print(out, crl)) { + BIO_free(out); + ossl_raise(eX509CRLError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +/* + * Gets X509v3 extensions as array of X509Ext objects + */ +static VALUE +ossl_x509crl_get_extensions(VALUE self) +{ + X509_CRL *crl; + int count, i; + X509_EXTENSION *ext; + VALUE ary; + + GetX509CRL(self, crl); + count = X509_CRL_get_ext_count(crl); + if (count < 0) { + OSSL_Debug("count < 0???"); + return rb_ary_new(); + } + ary = rb_ary_new2(count); + for (i=0; ilen; i++) { + OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext); + } + GetX509CRL(self, crl); + sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free); + crl->crl->extensions = NULL; + for (i=0; ilen; i++) { + ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]); + if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); + ossl_raise(eX509CRLError, NULL); + } + X509_EXTENSION_free(ext); + } + + return ary; +} + +static VALUE +ossl_x509crl_add_extension(VALUE self, VALUE extension) +{ + X509_CRL *crl; + X509_EXTENSION *ext; + + GetX509CRL(self, crl); + ext = DupX509ExtPtr(extension); + if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); + ossl_raise(eX509CRLError, NULL); + } + X509_EXTENSION_free(ext); + + return extension; +} + +/* + * INIT + */ +void +Init_ossl_x509crl() +{ + eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError); + + cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject); + + rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc); + rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1); + rb_define_copy_func(cX509CRL, ossl_x509crl_copy); + + rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0); + rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1); + rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0); + rb_define_method(cX509CRL, "issuer", ossl_x509crl_get_issuer, 0); + rb_define_method(cX509CRL, "issuer=", ossl_x509crl_set_issuer, 1); + rb_define_method(cX509CRL, "last_update", ossl_x509crl_get_last_update, 0); + rb_define_method(cX509CRL, "last_update=", ossl_x509crl_set_last_update, 1); + rb_define_method(cX509CRL, "next_update", ossl_x509crl_get_next_update, 0); + rb_define_method(cX509CRL, "next_update=", ossl_x509crl_set_next_update, 1); + rb_define_method(cX509CRL, "revoked", ossl_x509crl_get_revoked, 0); + rb_define_method(cX509CRL, "revoked=", ossl_x509crl_set_revoked, 1); + rb_define_method(cX509CRL, "add_revoked", ossl_x509crl_add_revoked, 1); + rb_define_method(cX509CRL, "sign", ossl_x509crl_sign, 2); + rb_define_method(cX509CRL, "verify", ossl_x509crl_verify, 1); + rb_define_method(cX509CRL, "to_der", ossl_x509crl_to_der, 0); + rb_define_method(cX509CRL, "to_pem", ossl_x509crl_to_pem, 0); + rb_define_alias(cX509CRL, "to_s", "to_pem"); + rb_define_method(cX509CRL, "to_text", ossl_x509crl_to_text, 0); + rb_define_method(cX509CRL, "extensions", ossl_x509crl_get_extensions, 0); + rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1); + rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_x509ext.c b/ruby_1_8_5/ext/openssl/ossl_x509ext.c new file mode 100644 index 0000000000..219f30d7e3 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509ext.c @@ -0,0 +1,456 @@ +/* + * $Id: ossl_x509ext.c,v 1.8.2.3 2005/11/22 22:28:51 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509Ext(klass, obj, ext) do { \ + if (!ext) { \ + ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_EXTENSION_free, ext); \ +} while (0) +#define GetX509Ext(obj, ext) do { \ + Data_Get_Struct(obj, X509_EXTENSION, ext); \ + if (!ext) { \ + ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509Ext(obj, ext) do { \ + OSSL_Check_Kind(obj, cX509Ext); \ + GetX509Ext(obj, ext); \ +} while (0) +#define MakeX509ExtFactory(klass, obj, ctx) do { \ + if (!(ctx = OPENSSL_malloc(sizeof(X509V3_CTX)))) \ + ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, 0); \ + obj = Data_Wrap_Struct(klass, 0, ossl_x509extfactory_free, ctx); \ +} while (0) +#define GetX509ExtFactory(obj, ctx) do { \ + Data_Get_Struct(obj, X509V3_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \ + } \ +} while (0) + +/* + * Classes + */ +VALUE cX509Ext; +VALUE cX509ExtFactory; +VALUE eX509ExtError; + +/* + * Public + */ +VALUE +ossl_x509ext_new(X509_EXTENSION *ext) +{ + X509_EXTENSION *new; + VALUE obj; + + if (!ext) { + new = X509_EXTENSION_new(); + } else { + new = X509_EXTENSION_dup(ext); + } + if (!new) { + ossl_raise(eX509ExtError, NULL); + } + WrapX509Ext(cX509Ext, obj, new); + + return obj; +} + +X509_EXTENSION * +GetX509ExtPtr(VALUE obj) +{ + X509_EXTENSION *ext; + + SafeGetX509Ext(obj, ext); + + return ext; +} + +X509_EXTENSION * +DupX509ExtPtr(VALUE obj) +{ + X509_EXTENSION *ext, *new; + + SafeGetX509Ext(obj, ext); + if (!(new = X509_EXTENSION_dup(ext))) { + ossl_raise(eX509ExtError, NULL); + } + + return new; +} + +/* + * Private + */ +/* + * Ext factory + */ +static void +ossl_x509extfactory_free(X509V3_CTX *ctx) +{ + OPENSSL_free(ctx); +} + +static VALUE +ossl_x509extfactory_alloc(VALUE klass) +{ + X509V3_CTX *ctx; + VALUE obj; + + MakeX509ExtFactory(klass, obj, ctx); + + return obj; +} + +static VALUE +ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert) +{ + X509V3_CTX *ctx; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@issuer_certificate", cert); + ctx->issuer_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */ + + return cert; +} + +static VALUE +ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert) +{ + X509V3_CTX *ctx; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@subject_certificate", cert); + ctx->subject_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */ + + return cert; +} + +static VALUE +ossl_x509extfactory_set_subject_req(VALUE self, VALUE req) +{ + X509V3_CTX *ctx; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@subject_request", req); + ctx->subject_req = GetX509ReqPtr(req); /* NO DUP NEEDED */ + + return req; +} + +static VALUE +ossl_x509extfactory_set_crl(VALUE self, VALUE crl) +{ + X509V3_CTX *ctx; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@crl", crl); + ctx->crl = GetX509CRLPtr(crl); /* NO DUP NEEDED */ + + return crl; +} + +static VALUE +ossl_x509extfactory_set_config(VALUE self, VALUE config) +{ +#ifdef HAVE_X509V3_SET_NCONF + X509V3_CTX *ctx; + CONF *conf; + + GetX509ExtFactory(self, ctx); + rb_iv_set(self, "@config", config); + conf = GetConfigPtr(config); /* NO DUP NEEDED */ + X509V3_set_nconf(ctx, conf); + + return config; +#else + rb_notimplement(); +#endif +} + +static VALUE +ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) +{ + /*X509V3_CTX *ctx;*/ + VALUE issuer_cert, subject_cert, subject_req, crl; + + /*GetX509ExtFactory(self, ctx);*/ + + rb_scan_args(argc, argv, "04", + &issuer_cert, &subject_cert, &subject_req, &crl); + if (!NIL_P(issuer_cert)) + ossl_x509extfactory_set_issuer_cert(self, issuer_cert); + if (!NIL_P(subject_cert)) + ossl_x509extfactory_set_subject_cert(self, subject_cert); + if (!NIL_P(subject_req)) + ossl_x509extfactory_set_subject_req(self, subject_req); + if (!NIL_P(crl)) + ossl_x509extfactory_set_crl(self, crl); + + return self; +} + +/* + * Array to X509_EXTENSION + * Structure: + * ["ln", "value", bool_critical] or + * ["sn", "value", bool_critical] or + * ["ln", "critical,value"] or the same for sn + * ["ln", "value"] => not critical + */ +static VALUE +ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) +{ + X509V3_CTX *ctx; + X509_EXTENSION *ext; + VALUE oid, value, critical, valstr, obj; + int nid; +#ifdef HAVE_X509V3_EXT_NCONF_NID + VALUE rconf; + CONF *conf; +#else + static LHASH *empty_lhash; +#endif + + rb_scan_args(argc, argv, "21", &oid, &value, &critical); + StringValue(oid); + StringValue(value); + if(NIL_P(critical)) critical = Qfalse; + + nid = OBJ_ln2nid(RSTRING(oid)->ptr); + if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr); + if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING(oid)->ptr); + valstr = rb_str_new2(RTEST(critical) ? "critical," : ""); + rb_str_append(valstr, value); + GetX509ExtFactory(self, ctx); +#ifdef HAVE_X509V3_EXT_NCONF_NID + rconf = rb_iv_get(self, "@config"); + conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf); + ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING(valstr)->ptr); +#else + if (!empty_lhash) empty_lhash = lh_new(NULL, NULL); + ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING(valstr)->ptr); +#endif + if (!ext){ + ossl_raise(eX509ExtError, "%s = %s", + RSTRING(oid)->ptr, RSTRING(value)->ptr); + } + WrapX509Ext(cX509Ext, obj, ext); + + return obj; +} + +/* + * Ext + */ +static VALUE +ossl_x509ext_alloc(VALUE klass) +{ + X509_EXTENSION *ext; + VALUE obj; + + if(!(ext = X509_EXTENSION_new())){ + ossl_raise(eX509ExtError, NULL); + } + WrapX509Ext(klass, obj, ext); + + return obj; +} + +static VALUE +ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE oid, value, critical; + unsigned char *p; + X509_EXTENSION *ext; + + GetX509Ext(self, ext); + if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){ + oid = ossl_to_der_if_possible(oid); + StringValue(oid); + p = RSTRING(oid)->ptr; + if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self), + &p, RSTRING(oid)->len)) + ossl_raise(eX509ExtError, NULL); + return self; + } + rb_funcall(self, rb_intern("oid="), 1, oid); + rb_funcall(self, rb_intern("value="), 1, value); + if(argc > 2) rb_funcall(self, rb_intern("critical="), 1, critical); + + return self; +} + +static VALUE +ossl_x509ext_set_oid(VALUE self, VALUE oid) +{ + X509_EXTENSION *ext; + ASN1_OBJECT *obj; + char *s; + + s = StringValuePtr(oid); + obj = OBJ_txt2obj(s, 0); + if(!obj) obj = OBJ_txt2obj(s, 1); + if(!obj) ossl_raise(eX509ExtError, NULL); + GetX509Ext(self, ext); + X509_EXTENSION_set_object(ext, obj); + + return oid; +} + +static VALUE +ossl_x509ext_set_value(VALUE self, VALUE data) +{ + X509_EXTENSION *ext; + ASN1_OCTET_STRING *asn1s; + char *s; + + data = ossl_to_der_if_possible(data); + StringValue(data); + if(!(s = OPENSSL_malloc(RSTRING(data)->len))) + ossl_raise(eX509ExtError, "malloc error"); + memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len); + if(!(asn1s = ASN1_OCTET_STRING_new())){ + free(s); + ossl_raise(eX509ExtError, NULL); + } + if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){ + free(s); + ASN1_OCTET_STRING_free(asn1s); + ossl_raise(eX509ExtError, NULL); + } + GetX509Ext(self, ext); + X509_EXTENSION_set_data(ext, asn1s); + + return data; +} + +static VALUE +ossl_x509ext_set_critical(VALUE self, VALUE flag) +{ + X509_EXTENSION *ext; + + GetX509Ext(self, ext); + X509_EXTENSION_set_critical(ext, RTEST(flag) ? 1 : 0); + + return flag; +} + +static VALUE +ossl_x509ext_get_oid(VALUE obj) +{ + X509_EXTENSION *ext; + ASN1_OBJECT *extobj; + BIO *out; + VALUE ret; + int nid; + + GetX509Ext(obj, ext); + extobj = X509_EXTENSION_get_object(ext); + if ((nid = OBJ_obj2nid(extobj)) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); + else{ + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509ExtError, NULL); + i2a_ASN1_OBJECT(out, extobj); + ret = ossl_membio2str(out); + } + + return ret; +} + +static VALUE +ossl_x509ext_get_value(VALUE obj) +{ + X509_EXTENSION *ext; + BIO *out; + VALUE ret; + + GetX509Ext(obj, ext); + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509ExtError, NULL); + if (!X509V3_EXT_print(out, ext, 0, 0)) + M_ASN1_OCTET_STRING_print(out, ext->value); + ret = ossl_membio2str(out); + + return ret; +} + +static VALUE +ossl_x509ext_get_critical(VALUE obj) +{ + X509_EXTENSION *ext; + + GetX509Ext(obj, ext); + return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse; +} + +static VALUE +ossl_x509ext_to_der(VALUE obj) +{ + X509_EXTENSION *ext; + unsigned char *p; + long len; + VALUE str; + + GetX509Ext(obj, ext); + if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0) + ossl_raise(eX509ExtError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_EXTENSION(ext, &p) < 0) + ossl_raise(eX509ExtError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * INIT + */ +void +Init_ossl_x509ext() +{ + eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError); + + cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject); + + rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc); + rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1); + + rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse); + rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse); + + rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); + rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); + rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); + rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); + rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); + rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1); + + cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); + rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); + rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1); + rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1); + rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1); + rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); + rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0); + rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0); + rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0); + rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_x509name.c b/ruby_1_8_5/ext/openssl/ossl_x509name.c new file mode 100644 index 0000000000..1a456f2c48 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509name.c @@ -0,0 +1,344 @@ +/* + * $Id: ossl_x509name.c,v 1.4.2.8 2004/12/27 07:55:56 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509Name(klass, obj, name) do { \ + if (!name) { \ + ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_NAME_free, name); \ +} while (0) +#define GetX509Name(obj, name) do { \ + Data_Get_Struct(obj, X509_NAME, name); \ + if (!name) { \ + ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ + } \ +} while (0) +#define SafeGetX509Name(obj, name) do { \ + OSSL_Check_Kind(obj, cX509Name); \ + GetX509Name(obj, name); \ +} while (0) + +#define OBJECT_TYPE_TEMPLATE \ + rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE")) +#define DEFAULT_OBJECT_TYPE \ + rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE")) + +/* + * Classes + */ +VALUE cX509Name; +VALUE eX509NameError; + +/* + * Public + */ +VALUE +ossl_x509name_new(X509_NAME *name) +{ + X509_NAME *new; + VALUE obj; + + if (!name) { + new = X509_NAME_new(); + } else { + new = X509_NAME_dup(name); + } + if (!new) { + ossl_raise(eX509NameError, NULL); + } + WrapX509Name(cX509Name, obj, new); + + return obj; +} + +X509_NAME * +GetX509NamePtr(VALUE obj) +{ + X509_NAME *name; + + SafeGetX509Name(obj, name); + + return name; +} + +/* + * Private + */ +static VALUE +ossl_x509name_alloc(VALUE klass) +{ + X509_NAME *name; + VALUE obj; + + if (!(name = X509_NAME_new())) { + ossl_raise(eX509NameError, NULL); + } + WrapX509Name(klass, obj, name); + + return obj; +} + +static int id_aref; +static VALUE ossl_x509name_add_entry(int, VALUE*, VALUE); +#define rb_aref(obj, key) rb_funcall(obj, id_aref, 1, key) + +static VALUE +ossl_x509name_init_i(VALUE i, VALUE args) +{ + VALUE self = rb_ary_entry(args, 0); + VALUE template = rb_ary_entry(args, 1); + VALUE entry[3]; + + Check_Type(i, T_ARRAY); + entry[0] = rb_ary_entry(i, 0); + entry[1] = rb_ary_entry(i, 1); + entry[2] = rb_ary_entry(i, 2); + if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]); + if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE; + ossl_x509name_add_entry(3, entry, self); + + return Qnil; +} + +static VALUE +ossl_x509name_initialize(int argc, VALUE *argv, VALUE self) +{ + X509_NAME *name; + VALUE arg, template; + + GetX509Name(self, name); + if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) { + return self; + } + else { + VALUE tmp = rb_check_array_type(arg); + if (!NIL_P(tmp)) { + VALUE args; + if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE; + args = rb_ary_new3(2, self, template); + rb_iterate(rb_each, tmp, ossl_x509name_init_i, args); + } + else{ + unsigned char *p; + VALUE str = ossl_to_der_if_possible(arg); + StringValue(str); + p = RSTRING(str)->ptr; + if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){ + ossl_raise(eX509NameError, NULL); + } + } + } + + return self; +} + +static +VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self) +{ + X509_NAME *name; + VALUE oid, value, type; + + rb_scan_args(argc, argv, "21", &oid, &value, &type); + StringValue(oid); + StringValue(value); + if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid); + GetX509Name(self, name); + if (!X509_NAME_add_entry_by_txt(name, RSTRING(oid)->ptr, NUM2INT(type), + RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) { + ossl_raise(eX509NameError, NULL); + } + + return self; +} + +static VALUE +ossl_x509name_to_s_old(VALUE self) +{ + X509_NAME *name; + char *buf; + VALUE str; + + GetX509Name(self, name); + buf = X509_NAME_oneline(name, NULL, 0); + str = rb_str_new2(buf); + OPENSSL_free(buf); + + return str; +} + +static VALUE +ossl_x509name_to_s(int argc, VALUE *argv, VALUE self) +{ + X509_NAME *name; + VALUE flag, str; + BIO *out; + unsigned long iflag; + + rb_scan_args(argc, argv, "01", &flag); + if (NIL_P(flag)) + return ossl_x509name_to_s_old(self); + else iflag = NUM2ULONG(flag); + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509NameError, NULL); + GetX509Name(self, name); + if (!X509_NAME_print_ex(out, name, 0, iflag)){ + BIO_free(out); + ossl_raise(eX509NameError, NULL); + } + str = ossl_membio2str(out); + + return str; +} + +static VALUE +ossl_x509name_to_a(VALUE self) +{ + X509_NAME *name; + X509_NAME_ENTRY *entry; + int i,entries; + char long_name[512]; + const char *short_name; + VALUE ary, ret; + + GetX509Name(self, name); + entries = X509_NAME_entry_count(name); + if (entries < 0) { + OSSL_Debug("name entries < 0!"); + return rb_ary_new(); + } + ret = rb_ary_new2(entries); + for (i=0; iobject)) { + ossl_raise(eX509NameError, NULL); + } + short_name = OBJ_nid2sn(OBJ_ln2nid(long_name)); + ary = rb_ary_new3(3, rb_str_new2(short_name), + rb_str_new(entry->value->data, entry->value->length), + INT2FIX(entry->value->type)); + rb_ary_push(ret, ary); + } + return ret; +} + +static int +ossl_x509name_cmp0(VALUE self, VALUE other) +{ + X509_NAME *name1, *name2; + + GetX509Name(self, name1); + SafeGetX509Name(other, name2); + + return X509_NAME_cmp(name1, name2); +} + +static VALUE +ossl_x509name_cmp(VALUE self, VALUE other) +{ + int result; + + result = ossl_x509name_cmp0(self, other); + if (result < 0) return INT2FIX(-1); + if (result > 1) return INT2FIX(1); + + return INT2FIX(0); +} + +static VALUE +ossl_x509name_eql(VALUE self, VALUE other) +{ + int result; + + if(CLASS_OF(other) != cX509Name) return Qfalse; + result = ossl_x509name_cmp0(self, other); + + return (result == 0) ? Qtrue : Qfalse; +} + +static VALUE +ossl_x509name_hash(VALUE self) +{ + X509_NAME *name; + unsigned long hash; + + GetX509Name(self, name); + + hash = X509_NAME_hash(name); + + return ULONG2NUM(hash); +} + +static VALUE +ossl_x509name_to_der(VALUE self) +{ + X509_NAME *name; + VALUE str; + long len; + unsigned char *p; + + GetX509Name(self, name); + if((len = i2d_X509_NAME(name, NULL)) <= 0) + ossl_raise(eX509NameError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_NAME(name, &p) <= 0) + ossl_raise(eX509NameError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +/* + * INIT + */ +void +Init_ossl_x509name() +{ + VALUE utf8str, ptrstr, ia5str, hash; + + id_aref = rb_intern("[]"); + eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError); + cX509Name = rb_define_class_under(mX509, "Name", rb_cObject); + + rb_define_alloc_func(cX509Name, ossl_x509name_alloc); + rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1); + rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1); + rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1); + rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0); + rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1); + rb_define_alias(cX509Name, "<=>", "cmp"); + rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1); + rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0); + rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0); + + utf8str = INT2NUM(V_ASN1_UTF8STRING); + ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING); + ia5str = INT2NUM(V_ASN1_IA5STRING); + rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str); + hash = rb_hash_new(); + RHASH(hash)->ifnone = utf8str; + rb_hash_aset(hash, rb_str_new2("C"), ptrstr); + rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr); + rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr); + rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr); + rb_hash_aset(hash, rb_str_new2("DC"), ia5str); + rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str); + rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str); + rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash); + + rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT)); + rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253)); + rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE)); + rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE)); +} diff --git a/ruby_1_8_5/ext/openssl/ossl_x509req.c b/ruby_1_8_5/ext/openssl/ossl_x509req.c new file mode 100644 index 0000000000..c1b1a3e619 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509req.c @@ -0,0 +1,466 @@ +/* + * $Id: ossl_x509req.c,v 1.5.2.2 2005/09/10 00:54:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509Req(klass, obj, req) do { \ + if (!req) { \ + ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_REQ_free, req); \ +} while (0) +#define GetX509Req(obj, req) do { \ + Data_Get_Struct(obj, X509_REQ, req); \ + if (!req) { \ + ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509Req(obj, req) do { \ + OSSL_Check_Kind(obj, cX509Req); \ + GetX509Req(obj, req); \ +} while (0) + +/* + * Classes + */ +VALUE cX509Req; +VALUE eX509ReqError; + +/* + * Public functions + */ +VALUE +ossl_x509req_new(X509_REQ *req) +{ + X509_REQ *new; + VALUE obj; + + if (!req) { + new = X509_REQ_new(); + } else { + new = X509_REQ_dup(req); + } + if (!new) { + ossl_raise(eX509ReqError, NULL); + } + WrapX509Req(cX509Req, obj, new); + + return obj; +} + +X509_REQ * +GetX509ReqPtr(VALUE obj) +{ + X509_REQ *req; + + SafeGetX509Req(obj, req); + + return req; +} + +X509_REQ * +DupX509ReqPtr(VALUE obj) +{ + X509_REQ *req, *new; + + SafeGetX509Req(obj, req); + if (!(new = X509_REQ_dup(req))) { + ossl_raise(eX509ReqError, NULL); + } + + return new; +} + +/* + * Private functions + */ +static VALUE +ossl_x509req_alloc(VALUE klass) +{ + X509_REQ *req; + VALUE obj; + + if (!(req = X509_REQ_new())) { + ossl_raise(eX509ReqError, NULL); + } + WrapX509Req(klass, obj, req); + + return obj; +} + +static VALUE +ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) +{ + BIO *in; + X509_REQ *req; + VALUE arg; + + if (rb_scan_args(argc, argv, "01", &arg) == 0) { + return self; + } + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + req = PEM_read_bio_X509_REQ(in, (X509_REQ **)&DATA_PTR(self), NULL, NULL); + if (!req) { + BIO_reset(in); + req = d2i_X509_REQ_bio(in, (X509_REQ **)&DATA_PTR(self)); + } + BIO_free(in); + if (!req) ossl_raise(eX509ReqError, NULL); + + return self; +} + +static VALUE +ossl_x509req_copy(VALUE self, VALUE other) +{ + X509_REQ *a, *b, *req; + + rb_check_frozen(self); + if (self == other) return self; + GetX509Req(self, a); + SafeGetX509Req(other, b); + if (!(req = X509_REQ_dup(b))) { + ossl_raise(eX509ReqError, NULL); + } + X509_REQ_free(a); + DATA_PTR(self) = req; + + return self; +} + +static VALUE +ossl_x509req_to_pem(VALUE self) +{ + X509_REQ *req; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509Req(self, req); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509ReqError, NULL); + } + if (!PEM_write_bio_X509_REQ(out, req)) { + BIO_free(out); + ossl_raise(eX509ReqError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +static VALUE +ossl_x509req_to_der(VALUE self) +{ + X509_REQ *req; + VALUE str; + long len; + unsigned char *p; + + GetX509Req(self, req); + if ((len = i2d_X509_REQ(req, NULL)) <= 0) + ossl_raise(eX509CertError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if (i2d_X509_REQ(req, &p) <= 0) + ossl_raise(eX509ReqError, NULL); + ossl_str_adjust(str, p); + + return str; +} + +static VALUE +ossl_x509req_to_text(VALUE self) +{ + X509_REQ *req; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509Req(self, req); + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509ReqError, NULL); + } + if (!X509_REQ_print(out, req)) { + BIO_free(out); + ossl_raise(eX509ReqError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +#if 0 +/* + * Makes X509 from X509_REQuest + */ +static VALUE +ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key) +{ + X509_REQ *req; + X509 *x509; + + GetX509Req(self, req); + ... + if (!(x509 = X509_REQ_to_X509(req, d, pkey))) { + ossl_raise(eX509ReqError, NULL); + } + + return ossl_x509_new(x509); +} +#endif + +static VALUE +ossl_x509req_get_version(VALUE self) +{ + X509_REQ *req; + long version; + + GetX509Req(self, req); + version = X509_REQ_get_version(req); + + return LONG2FIX(version); +} + +static VALUE +ossl_x509req_set_version(VALUE self, VALUE version) +{ + X509_REQ *req; + long ver; + + if ((ver = FIX2LONG(version)) < 0) { + ossl_raise(eX509ReqError, "version must be >= 0!"); + } + GetX509Req(self, req); + if (!X509_REQ_set_version(req, ver)) { + ossl_raise(eX509ReqError, NULL); + } + + return version; +} + +static VALUE +ossl_x509req_get_subject(VALUE self) +{ + X509_REQ *req; + X509_NAME *name; + + GetX509Req(self, req); + if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */ + ossl_raise(eX509ReqError, NULL); + } + + return ossl_x509name_new(name); +} + +static VALUE +ossl_x509req_set_subject(VALUE self, VALUE subject) +{ + X509_REQ *req; + + GetX509Req(self, req); + /* DUPs name */ + if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) { + ossl_raise(eX509ReqError, NULL); + } + + return subject; +} + +static VALUE +ossl_x509req_get_signature_algorithm(VALUE self) +{ + X509_REQ *req; + BIO *out; + BUF_MEM *buf; + VALUE str; + + GetX509Req(self, req); + + if (!(out = BIO_new(BIO_s_mem()))) { + ossl_raise(eX509ReqError, NULL); + } + if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) { + BIO_free(out); + ossl_raise(eX509ReqError, NULL); + } + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + return str; +} + +static VALUE +ossl_x509req_get_public_key(VALUE self) +{ + X509_REQ *req; + EVP_PKEY *pkey; + + GetX509Req(self, req); + if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */ + ossl_raise(eX509ReqError, NULL); + } + + return ossl_pkey_new(pkey); /* NO DUP - OK */ +} + +static VALUE +ossl_x509req_set_public_key(VALUE self, VALUE key) +{ + X509_REQ *req; + EVP_PKEY *pkey; + + GetX509Req(self, req); + pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ + if (!X509_REQ_set_pubkey(req, pkey)) { + ossl_raise(eX509ReqError, NULL); + } + + return key; +} + +static VALUE +ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) +{ + X509_REQ *req; + EVP_PKEY *pkey; + const EVP_MD *md; + + GetX509Req(self, req); + pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ + md = GetDigestPtr(digest); + if (!X509_REQ_sign(req, pkey, md)) { + ossl_raise(eX509ReqError, NULL); + } + + return self; +} + +/* + * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' + */ +static VALUE +ossl_x509req_verify(VALUE self, VALUE key) +{ + X509_REQ *req; + EVP_PKEY *pkey; + int i; + + GetX509Req(self, req); + pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ + if ((i = X509_REQ_verify(req, pkey)) < 0) { + ossl_raise(eX509ReqError, NULL); + } + if (i > 0) { + return Qtrue; + } + + return Qfalse; +} + +static VALUE +ossl_x509req_get_attributes(VALUE self) +{ + X509_REQ *req; + int count, i; + X509_ATTRIBUTE *attr; + VALUE ary; + + GetX509Req(self, req); + + count = X509_REQ_get_attr_count(req); + if (count < 0) { + OSSL_Debug("count < 0???"); + return rb_ary_new(); + } + ary = rb_ary_new2(count); + for (i=0; ilen; i++) { + OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr); + } + GetX509Req(self, req); + sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free); + req->req_info->attributes = NULL; + for (i=0;ilen; i++) { + item = RARRAY(ary)->ptr[i]; + attr = DupX509AttrPtr(item); + if (!X509_REQ_add1_attr(req, attr)) { + ossl_raise(eX509ReqError, NULL); + } + } + return ary; +} + +static VALUE +ossl_x509req_add_attribute(VALUE self, VALUE attr) +{ + X509_REQ *req; + + GetX509Req(self, req); + if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) { + ossl_raise(eX509ReqError, NULL); + } + + return attr; +} + +/* + * X509_REQUEST init + */ +void +Init_ossl_x509req() +{ + eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError); + + cX509Req = rb_define_class_under(mX509, "Request", rb_cObject); + + rb_define_alloc_func(cX509Req, ossl_x509req_alloc); + rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1); + rb_define_copy_func(cX509Req, ossl_x509req_copy); + + rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0); + rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0); + rb_define_alias(cX509Req, "to_s", "to_pem"); + rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0); + rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0); + rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1); + rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0); + rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1); + rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0); + rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0); + rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1); + rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2); + rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1); + rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0); + rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1); + rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_x509revoked.c b/ruby_1_8_5/ext/openssl/ossl_x509revoked.c new file mode 100644 index 0000000000..a0f2f00aa5 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509revoked.c @@ -0,0 +1,229 @@ +/* + * $Id: ossl_x509revoked.c,v 1.2.2.1 2004/12/15 01:54:38 matz Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define WrapX509Rev(klass, obj, rev) do { \ + if (!rev) { \ + ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_REVOKED_free, rev); \ +} while (0) +#define GetX509Rev(obj, rev) do { \ + Data_Get_Struct(obj, X509_REVOKED, rev); \ + if (!rev) { \ + ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509Rev(obj, rev) do { \ + OSSL_Check_Kind(obj, cX509Rev); \ + GetX509Rev(obj, rev); \ +} while (0) + +/* + * Classes + */ +VALUE cX509Rev; +VALUE eX509RevError; + +/* + * PUBLIC + */ +VALUE +ossl_x509revoked_new(X509_REVOKED *rev) +{ + X509_REVOKED *new; + VALUE obj; + + if (!rev) { + new = X509_REVOKED_new(); + } else { + new = X509_REVOKED_dup(rev); + } + if (!new) { + ossl_raise(eX509RevError, NULL); + } + WrapX509Rev(cX509Rev, obj, new); + + return obj; +} + +X509_REVOKED * +DupX509RevokedPtr(VALUE obj) +{ + X509_REVOKED *rev, *new; + + SafeGetX509Rev(obj, rev); + if (!(new = X509_REVOKED_dup(rev))) { + ossl_raise(eX509RevError, NULL); + } + + return new; +} + +/* + * PRIVATE + */ +static VALUE +ossl_x509revoked_alloc(VALUE klass) +{ + X509_REVOKED *rev; + VALUE obj; + + if (!(rev = X509_REVOKED_new())) { + ossl_raise(eX509RevError, NULL); + } + WrapX509Rev(klass, obj, rev); + + return obj; +} + +static VALUE +ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self) +{ + /* EMPTY */ + return self; +} + +static VALUE +ossl_x509revoked_get_serial(VALUE self) +{ + X509_REVOKED *rev; + + GetX509Rev(self, rev); + + return asn1integer_to_num(rev->serialNumber); +} + +static VALUE +ossl_x509revoked_set_serial(VALUE self, VALUE num) +{ + X509_REVOKED *rev; + + GetX509Rev(self, rev); + rev->serialNumber = num_to_asn1integer(num, rev->serialNumber); + + return num; +} + +static VALUE +ossl_x509revoked_get_time(VALUE self) +{ + X509_REVOKED *rev; + + GetX509Rev(self, rev); + + return asn1time_to_time(rev->revocationDate); +} + +static VALUE +ossl_x509revoked_set_time(VALUE self, VALUE time) +{ + X509_REVOKED *rev; + time_t sec; + + sec = time_to_time_t(time); + GetX509Rev(self, rev); + if (!X509_time_adj(rev->revocationDate, 0, &sec)) { + ossl_raise(eX509RevError, NULL); + } + + return time; +} +/* + * Gets X509v3 extensions as array of X509Ext objects + */ +static VALUE +ossl_x509revoked_get_extensions(VALUE self) +{ + X509_REVOKED *rev; + int count, i; + X509_EXTENSION *ext; + VALUE ary; + + GetX509Rev(self, rev); + count = X509_REVOKED_get_ext_count(rev); + if (count < 0) { + OSSL_Debug("count < 0???"); + return rb_ary_new(); + } + ary = rb_ary_new2(count); + for (i=0; ilen; i++) { + OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext); + } + GetX509Rev(self, rev); + sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free); + rev->extensions = NULL; + for (i=0; ilen; i++) { + item = RARRAY(ary)->ptr[i]; + ext = DupX509ExtPtr(item); + if(!X509_REVOKED_add_ext(rev, ext, -1)) { + ossl_raise(eX509RevError, NULL); + } + } + + return ary; +} + +static VALUE +ossl_x509revoked_add_extension(VALUE self, VALUE ext) +{ + X509_REVOKED *rev; + + GetX509Rev(self, rev); + if(!X509_REVOKED_add_ext(rev, DupX509ExtPtr(ext), -1)) { + ossl_raise(eX509RevError, NULL); + } + + return ext; +} + +/* + * INIT + */ +void +Init_ossl_x509revoked() +{ + eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError); + + cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject); + + rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc); + rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1); + + rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0); + rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1); + rb_define_method(cX509Rev, "time", ossl_x509revoked_get_time, 0); + rb_define_method(cX509Rev, "time=", ossl_x509revoked_set_time, 1); + rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0); + rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1); + rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1); +} + diff --git a/ruby_1_8_5/ext/openssl/ossl_x509store.c b/ruby_1_8_5/ext/openssl/ossl_x509store.c new file mode 100644 index 0000000000..360769e612 --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ossl_x509store.c @@ -0,0 +1,613 @@ +/* + * $Id: ossl_x509store.c,v 1.2.2.5 2005/09/10 00:54:29 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" +#include + +#define WrapX509Store(klass, obj, st) do { \ + if (!st) { \ + ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, X509_STORE_free, st); \ +} while (0) +#define GetX509Store(obj, st) do { \ + Data_Get_Struct(obj, X509_STORE, st); \ + if (!st) { \ + ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ + } \ +} while (0) +#define SafeGetX509Store(obj, st) do { \ + OSSL_Check_Kind(obj, cX509Store); \ + GetX509Store(obj, st); \ +} while (0) + +#define WrapX509StCtx(klass, obj, ctx) do { \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, ossl_x509stctx_free, ctx); \ +} while (0) +#define GetX509StCtx(obj, ctx) do { \ + Data_Get_Struct(obj, X509_STORE_CTX, ctx); \ + if (!ctx) { \ + ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \ + } \ +} while (0) +#define SafeGetX509StCtx(obj, storep) do { \ + OSSL_Check_Kind(obj, cX509StoreContext); \ + GetX509Store(obj, ctx); \ +} while (0) + +/* + * Classes + */ +VALUE cX509Store; +VALUE cX509StoreContext; +VALUE eX509StoreError; + +/* + * Public functions + */ +VALUE +ossl_x509store_new(X509_STORE *store) +{ + VALUE obj; + + WrapX509Store(cX509Store, obj, store); + + return obj; +} + +X509_STORE * +GetX509StorePtr(VALUE obj) +{ + X509_STORE *store; + + SafeGetX509Store(obj, store); + + return store; +} + +X509_STORE * +DupX509StorePtr(VALUE obj) +{ + X509_STORE *store; + + SafeGetX509Store(obj, store); + CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + + return store; +} + +/* + * Private functions + */ +static VALUE +ossl_x509store_alloc(VALUE klass) +{ + X509_STORE *store; + VALUE obj; + + if((store = X509_STORE_new()) == NULL){ + ossl_raise(eX509StoreError, NULL); + } + WrapX509Store(klass, obj, store); + + return obj; +} + +/* + * General callback for OpenSSL verify + */ +static VALUE +ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) +{ + X509_STORE *store; + + GetX509Store(self, store); + X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb); + rb_iv_set(self, "@verify_callback", cb); + + return cb; +} + +static VALUE +ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) +{ + X509_STORE *store; + + GetX509Store(self, store); + X509_STORE_set_verify_cb_func(store, ossl_verify_cb); + ossl_x509store_set_vfy_cb(self, Qnil); + +#if (OPENSSL_VERSION_NUMBER < 0x00907000L) + rb_iv_set(self, "@flags", INT2NUM(0)); + rb_iv_set(self, "@purpose", INT2NUM(0)); + rb_iv_set(self, "@trust", INT2NUM(0)); +#endif + + /* last verification status */ + rb_iv_set(self, "@error", Qnil); + rb_iv_set(self, "@error_string", Qnil); + rb_iv_set(self, "@chain", Qnil); + rb_iv_set(self, "@time", Qnil); + + return self; +} + +static VALUE +ossl_x509store_set_flags(VALUE self, VALUE flags) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) + X509_STORE *store; + long f = NUM2LONG(flags); + + GetX509Store(self, store); + X509_STORE_set_flags(store, f); +#else + rb_iv_set(self, "@flags", flags); +#endif + + return flags; +} + +static VALUE +ossl_x509store_set_purpose(VALUE self, VALUE purpose) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) + X509_STORE *store; + long p = NUM2LONG(purpose); + + GetX509Store(self, store); + X509_STORE_set_purpose(store, p); +#else + rb_iv_set(self, "@purpose", purpose); +#endif + + return purpose; +} + +static VALUE +ossl_x509store_set_trust(VALUE self, VALUE trust) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) + X509_STORE *store; + long t = NUM2LONG(trust); + + GetX509Store(self, store); + X509_STORE_set_trust(store, t); +#else + rb_iv_set(self, "@trust", trust); +#endif + + return trust; +} + +static VALUE +ossl_x509store_set_time(VALUE self, VALUE time) +{ + rb_iv_set(self, "@time", time); + return time; +} + +static VALUE +ossl_x509store_add_file(VALUE self, VALUE file) +{ + X509_STORE *store; + X509_LOOKUP *lookup; + char *path = NULL; + + if(file != Qnil){ + Check_SafeStr(file); + path = RSTRING(file)->ptr; + } + GetX509Store(self, store); + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if(lookup == NULL) ossl_raise(eX509StoreError, NULL); + if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){ + ossl_raise(eX509StoreError, NULL); + } + + return self; +} + +static VALUE +ossl_x509store_add_path(VALUE self, VALUE dir) +{ + X509_STORE *store; + X509_LOOKUP *lookup; + char *path = NULL; + + if(dir != Qnil){ + Check_SafeStr(dir); + path = RSTRING(dir)->ptr; + } + GetX509Store(self, store); + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if(lookup == NULL) ossl_raise(eX509StoreError, NULL); + if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){ + ossl_raise(eX509StoreError, NULL); + } + + return self; +} + +static VALUE +ossl_x509store_set_default_paths(VALUE self) +{ + X509_STORE *store; + + GetX509Store(self, store); + if (X509_STORE_set_default_paths(store) != 1){ + ossl_raise(eX509StoreError, NULL); + } + + return Qnil; +} + +static VALUE +ossl_x509store_add_cert(VALUE self, VALUE arg) +{ + X509_STORE *store; + X509 *cert; + + cert = GetX509CertPtr(arg); /* NO NEED TO DUP */ + GetX509Store(self, store); + if (X509_STORE_add_cert(store, cert) != 1){ + ossl_raise(eX509StoreError, NULL); + } + + return self; +} + +static VALUE +ossl_x509store_add_crl(VALUE self, VALUE arg) +{ + X509_STORE *store; + X509_CRL *crl; + + crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */ + GetX509Store(self, store); + if (X509_STORE_add_crl(store, crl) != 1){ + ossl_raise(eX509StoreError, NULL); + } + + return self; +} + +static VALUE ossl_x509stctx_get_err(VALUE); +static VALUE ossl_x509stctx_get_err_string(VALUE); +static VALUE ossl_x509stctx_get_chain(VALUE); + +static VALUE +ossl_x509store_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE cert, chain; + VALUE ctx, proc, result; + + rb_scan_args(argc, argv, "11", &cert, &chain); + ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain); + proc = rb_block_given_p() ? rb_block_proc() : + rb_iv_get(self, "@verify_callback"); + rb_iv_set(ctx, "@verify_callback", proc); + result = rb_funcall(ctx, rb_intern("verify"), 0); + + rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx)); + rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx)); + rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx)); + + return result; +} + +/* + * Public Functions + */ +static void ossl_x509stctx_free(X509_STORE_CTX*); + +VALUE +ossl_x509stctx_new(X509_STORE_CTX *ctx) +{ + VALUE obj; + + WrapX509StCtx(cX509StoreContext, obj, ctx); + + return obj; +} + +VALUE +ossl_x509stctx_clear_ptr(VALUE obj) +{ + OSSL_Check_Kind(obj, cX509StoreContext); + RDATA(obj)->data = NULL; + + return obj; +} + +/* + * Private functions + */ +static void +ossl_x509stctx_free(X509_STORE_CTX *ctx) +{ + if(ctx->untrusted) + sk_X509_pop_free(ctx->untrusted, X509_free); + if(ctx->cert) + X509_free(ctx->cert); + X509_STORE_CTX_free(ctx); +} + +static VALUE +ossl_x509stctx_alloc(VALUE klass) +{ + X509_STORE_CTX *ctx; + VALUE obj; + + if((ctx = X509_STORE_CTX_new()) == NULL){ + ossl_raise(eX509StoreError, NULL); + } + WrapX509StCtx(klass, obj, ctx); + + return obj; +} + +static VALUE ossl_x509stctx_set_flags(VALUE, VALUE); +static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE); +static VALUE ossl_x509stctx_set_trust(VALUE, VALUE); +static VALUE ossl_x509stctx_set_time(VALUE, VALUE); + +static VALUE +ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE store, cert, chain, t; + X509_STORE_CTX *ctx; + X509_STORE *x509st; + X509 *x509 = NULL; + STACK_OF(X509) *x509s = NULL; + + rb_scan_args(argc, argv, "12", &store, &cert, &chain); + GetX509StCtx(self, ctx); + SafeGetX509Store(store, x509st); + if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ + if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); +#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) + if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ + sk_X509_pop_free(x509s, X509_free); + ossl_raise(eX509StoreError, NULL); + } +#else + X509_STORE_CTX_init(ctx, x509st, x509, x509s); + ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags")); + ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose")); + ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust")); +#endif + if (!NIL_P(t = rb_iv_get(store, "@time"))) + ossl_x509stctx_set_time(self, t); + rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback")); + rb_iv_set(self, "@cert", cert); + + return self; +} + +static VALUE +ossl_x509stctx_verify(VALUE self) +{ + X509_STORE_CTX *ctx; + int result; + + GetX509StCtx(self, ctx); + X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, + (void*)rb_iv_get(self, "@verify_callback")); + result = X509_verify_cert(ctx); + + return result ? Qtrue : Qfalse; +} + +static VALUE +ossl_x509stctx_get_chain(VALUE self) +{ + X509_STORE_CTX *ctx; + STACK_OF(X509) *chain; + X509 *x509; + int i, num; + VALUE ary; + + GetX509StCtx(self, ctx); + if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){ + return Qnil; + } + if((num = sk_X509_num(chain)) < 0){ + OSSL_Debug("certs in chain < 0???"); + return rb_ary_new(); + } + ary = rb_ary_new2(num); + for(i = 0; i < num; i++) { + x509 = sk_X509_value(chain, i); + rb_ary_push(ary, ossl_x509_new(x509)); + } + + return ary; +} + +static VALUE +ossl_x509stctx_get_err(VALUE self) +{ + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + + return INT2FIX(X509_STORE_CTX_get_error(ctx)); +} + +static VALUE +ossl_x509stctx_set_error(VALUE self, VALUE err) +{ + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + X509_STORE_CTX_set_error(ctx, FIX2INT(err)); + + return err; +} + +static VALUE +ossl_x509stctx_get_err_string(VALUE self) +{ + X509_STORE_CTX *ctx; + long err; + + GetX509StCtx(self, ctx); + err = X509_STORE_CTX_get_error(ctx); + + return rb_str_new2(X509_verify_cert_error_string(err)); +} + +static VALUE +ossl_x509stctx_get_err_depth(VALUE self) +{ + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + + return INT2FIX(X509_STORE_CTX_get_error_depth(ctx)); +} + +static VALUE +ossl_x509stctx_get_curr_cert(VALUE self) +{ + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + + return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx)); +} + +static VALUE +ossl_x509stctx_get_curr_crl(VALUE self) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + if(!ctx->current_crl) return Qnil; + + return ossl_x509crl_new(ctx->current_crl); +#else + return Qnil; +#endif +} + +static VALUE +ossl_x509stctx_cleanup(VALUE self) +{ + X509_STORE_CTX *ctx; + + GetX509StCtx(self, ctx); + X509_STORE_CTX_cleanup(ctx); + + return self; +} + +static VALUE +ossl_x509stctx_set_flags(VALUE self, VALUE flags) +{ + X509_STORE_CTX *store; + long f = NUM2LONG(flags); + + GetX509StCtx(self, store); + X509_STORE_CTX_set_flags(store, f); + + return flags; +} + +static VALUE +ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) +{ + X509_STORE_CTX *store; + long p = NUM2LONG(purpose); + + GetX509StCtx(self, store); + X509_STORE_CTX_set_purpose(store, p); + + return purpose; +} + +static VALUE +ossl_x509stctx_set_trust(VALUE self, VALUE trust) +{ + X509_STORE_CTX *store; + long t = NUM2LONG(trust); + + GetX509StCtx(self, store); + X509_STORE_CTX_set_trust(store, t); + + return trust; +} + +static VALUE +ossl_x509stctx_set_time(VALUE self, VALUE time) +{ + X509_STORE_CTX *store; + long t; + + t = NUM2LONG(rb_Integer(time)); + GetX509StCtx(self, store); + X509_STORE_CTX_set_time(store, 0, t); + + return time; +} + +/* + * INIT + */ +void +Init_ossl_x509store() +{ + VALUE x509stctx; + + eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError); + + cX509Store = rb_define_class_under(mX509, "Store", rb_cObject); + rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse); + rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse); + rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse); + rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse); + rb_define_alloc_func(cX509Store, ossl_x509store_alloc); + rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1); + rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1); + rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1); + rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1); + rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1); + rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1); + rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1); + rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1); + rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0); + rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1); + rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1); + rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1); + + cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject); + x509stctx = cX509StoreContext; + rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc); + rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1); + rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0); + rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0); + rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0); + rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1); + rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0); + rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0); + rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0); + rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0); + rb_define_method(x509stctx,"cleanup", ossl_x509stctx_cleanup, 0); + rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1); + rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1); + rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1); + rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1); + +} diff --git a/ruby_1_8_5/ext/openssl/ruby_missing.h b/ruby_1_8_5/ext/openssl/ruby_missing.h new file mode 100644 index 0000000000..f673bb157a --- /dev/null +++ b/ruby_1_8_5/ext/openssl/ruby_missing.h @@ -0,0 +1,18 @@ +/* + * $Id: ruby_missing.h,v 1.3 2003/09/06 08:56:57 gotoyuzo Exp $ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2003 Michal Rokos + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_RUBY_MISSING_H_) +#define _OSS_RUBY_MISSING_H_ + +#define rb_define_copy_func(klass, func) \ + rb_define_method(klass, "initialize_copy", func, 1) + +#endif /* _OSS_RUBY_MISSING_H_ */ + -- cgit v1.2.3