From c9dc0164b8ad1cb23faf6120749bcc349a7bfd45 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 29 Aug 2016 05:47:09 +0000 Subject: import Ruby/OpenSSL 2.0.0.beta.1 * NEWS, {ext,test,sample}/openssl: Import Ruby/OpenSSL 2.0.0.beta.1. ext/openssl is now converted into a default gem. The full commit history since r55538 can be found at: https://github.com/ruby/openssl/compare/08e1881f5663...v2.0.0.beta.1 [Feature #9612] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 181 ++++++++++++++++++++++------------------------------- 1 file changed, 74 insertions(+), 107 deletions(-) (limited to 'ext/openssl/ossl.c') diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 83baa7b63c..a9000f25a3 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -9,40 +9,7 @@ */ #include "ossl.h" #include /* for ossl_raise */ - -/* - * String to HEXString conversion - */ -int -string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len) -{ - static const char hex[]="0123456789abcdef"; - int i, len; - - if (buf_len < 0 || buf_len > INT_MAX / 2) { /* PARANOIA? */ - return -1; - } - len = 2 * buf_len; - 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; -} +#include /* for OpenSSL < 1.1.0 locks */ /* * Data Conversion @@ -77,7 +44,7 @@ STACK_OF(type) * \ ossl_protect_##name##_ary2sk(VALUE ary, int *status) \ { \ return (STACK_OF(type)*)rb_protect( \ - (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \ + (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \ ary, \ status); \ } \ @@ -97,7 +64,7 @@ OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr) #define OSSL_IMPL_SK2ARY(name, type) \ VALUE \ -ossl_##name##_sk2ary(STACK_OF(type) *sk) \ +ossl_##name##_sk2ary(const STACK_OF(type) *sk) \ { \ type *t; \ int i, num; \ @@ -136,7 +103,7 @@ ossl_buf2str(char *buf, int len) VALUE str; int status = 0; - str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status); + str = rb_protect((VALUE (*)(VALUE))ossl_str_new, len, &status); if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len); OPENSSL_free(buf); if(status) rb_jump_tag(status); @@ -144,6 +111,21 @@ ossl_buf2str(char *buf, int len) return str; } +void +ossl_bin2hex(unsigned char *in, char *out, size_t inlen) +{ + const char *hex = "0123456789abcdef"; + size_t i; + + assert(inlen <= LONG_MAX / 2); + for (i = 0; i < inlen; i++) { + unsigned char p = in[i]; + + out[i * 2 + 0] = hex[p >> 4]; + out[i * 2 + 1] = hex[p & 0x0f]; + } +} + /* * our default PEM callback */ @@ -242,54 +224,54 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_) int ossl_store_ctx_ex_verify_cb_idx; int ossl_store_ex_verify_cb_idx; -VALUE +struct ossl_verify_cb_args { + VALUE proc; + VALUE preverify_ok; + VALUE store_ctx; +}; + +static 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); + args->preverify_ok, args->store_ctx); } int -ossl_verify_cb(int ok, X509_STORE_CTX *ctx) +ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx) { - VALUE proc, rctx, ret; + VALUE rctx, ret; struct ossl_verify_cb_args args; - int state = 0; + int state; - proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx); - if (!proc) - proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx); - if (!proc) + if (NIL_P(proc)) return ok; - if (!NIL_P(proc)) { - ret = Qfalse; - rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, - (VALUE)ctx, &state); + + ret = Qfalse; + rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state); + if (state) { + rb_set_errinfo(Qnil); + rb_warn("StoreContext initialization failure"); + } + else { + args.proc = proc; + args.preverify_ok = ok ? Qtrue : Qfalse; + args.store_ctx = rctx; + ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state); if (state) { rb_set_errinfo(Qnil); - rb_warn("StoreContext initialization failure"); - } - else { - args.proc = proc; - args.preverify_ok = ok ? Qtrue : Qfalse; - args.store_ctx = rctx; - ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state); - if (state) { - rb_set_errinfo(Qnil); - rb_warn("exception in verify_callback is ignored"); - } - 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; + rb_warn("exception in verify_callback is ignored"); } + 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; @@ -453,24 +435,14 @@ ossl_debug_get(VALUE self) * call-seq: * OpenSSL.debug = boolean -> boolean * - * Turns on or off CRYPTO_MEM_CHECK. - * Also shows some debugging message on stderr. + * Turns on or off debug mode. With debug mode, all erros added to the OpenSSL + * error queue will be printed to stderr. */ static VALUE ossl_debug_set(VALUE self, VALUE val) { - VALUE old = dOSSL; - dOSSL = val; - - if (old != dOSSL) { - if (dOSSL == Qtrue) { - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); - } else if (old == Qtrue) { - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); - fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); - } - } + dOSSL = RTEST(val) ? Qtrue : Qfalse; + return val; } @@ -483,9 +455,8 @@ ossl_debug_set(VALUE self, VALUE val) * so otherwise will result in an error. * * === Examples - * - * OpenSSL.fips_mode = true # turn FIPS mode on - * OpenSSL.fips_mode = false # and off again + * OpenSSL.fips_mode = true # turn FIPS mode on + * OpenSSL.fips_mode = false # and off again */ static VALUE ossl_fips_mode_set(VALUE self, VALUE enabled) @@ -512,7 +483,6 @@ ossl_fips_mode_set(VALUE self, VALUE enabled) /** * Stores locks needed for OpenSSL thread safety */ -#include "ruby/thread_native.h" static rb_nativethread_lock_t *ossl_locks; static void @@ -602,20 +572,6 @@ static void Init_ossl_locks(void) * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the * OpenSSL[http://www.openssl.org/] library. * - * = Install - * - * OpenSSL comes bundled with the Standard Library of Ruby. - * - * This means the OpenSSL extension is compiled with Ruby and packaged on - * build. During compile time, Ruby will need to link against the OpenSSL - * library on your system. However, you cannot use openssl provided by Apple to - * build standard library openssl. - * - * If you use OSX, you should install another openssl and run ```./configure - * --with-openssl-dir=/path/to/another-openssl```. For Homebrew user, run `brew - * install openssl` and then ```./configure --with-openssl-dir=`brew --prefix - * openssl` ```. - * * = Examples * * All examples assume you have loaded OpenSSL with: @@ -660,10 +616,12 @@ static void Init_ossl_locks(void) * * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' * key2.public? # => true + * key2.private? # => true * * or * * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' + * key3.public? # => true * key3.private? # => false * * === Loading an Encrypted Key @@ -910,7 +868,7 @@ static void Init_ossl_locks(void) * ca_key = OpenSSL::PKey::RSA.new 2048 * pass_phrase = 'my secure pass phrase goes here' * - * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'AES-128-CBC' * * open 'ca_key.pem', 'w', 0400 do |io| * io.write ca_key.export(cipher, pass_phrase) @@ -1063,15 +1021,21 @@ static void Init_ossl_locks(void) * SSLSocket#connect must be called to initiate the SSL handshake and start * encryption. A key and certificate are not required for the client socket. * + * Note that SSLSocket#close doesn't close the underlying socket by default. Set + * SSLSocket#sync_close to true if you want. + * * require 'socket' * * tcp_socket = TCPSocket.new 'localhost', 5000 * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context + * ssl_client.sync_close = true * ssl_client.connect * * ssl_client.puts "hello server!" * puts ssl_client.gets * + * ssl_client.close # shutdown the TLS connection and close tcp_socket + * * === Peer Verification * * An unverified SSL connection does not provide much security. For enhanced @@ -1160,11 +1124,14 @@ Init_openssl(void) /* * Boolean indicating whether OpenSSL is FIPS-enabled or not */ + rb_define_const(mOSSL, "OPENSSL_FIPS", #ifdef OPENSSL_FIPS - rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue); + Qtrue #else - rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse); + Qfalse #endif + ); + rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1); /* -- cgit v1.2.3