Commit 7d5b02fc authored by Antonio Terceiro's avatar Antonio Terceiro

New upstream version 2.1.1

parent fe805d67
......@@ -18,13 +18,11 @@ matrix:
fast_finish: true
include:
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=openssl-1.0.2
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=openssl-1.0.0
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=openssl-1.0.1
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=openssl-1.0.2
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=openssl-1.1.0
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=libressl-2.3
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=libressl-2.4
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=libressl-2.5
- env: RUBY_VERSION=ruby-2.4 OPENSSL_VERSION=libressl-2.6
- language: ruby
rvm: ruby-head
before_install:
......
Version 2.1.0
=============
Notable changes
---------------
* Support for OpenSSL versions before 1.0.1 and LibreSSL versions before 2.5
is removed.
[[GitHub #86]](https://github.com/ruby/openssl/pull/86)
* OpenSSL::BN#negative?, #+@, and #-@ are added.
* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when
certificate verification fails.
[[GitHub #99]](https://github.com/ruby/openssl/pull/99)
* OpenSSL::KDF module is newly added. In addition to PBKDF2-HMAC that has moved
from OpenSSL::PKCS5, scrypt and HKDF are supported.
[[GitHub #109]](https://github.com/ruby/openssl/pull/109)
[[GitHub #173]](https://github.com/ruby/openssl/pull/173)
* OpenSSL.fips_mode is added. We had the setter, but not the getter.
[[GitHub #125]](https://github.com/ruby/openssl/pull/125)
* OpenSSL::OCSP::Request#signed? is added.
* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode
no longer wrongly treats the end-of-contents octets as part of the content.
OpenSSL::ASN1::ASN1Data#infinite_length is renamed to #indefinite_length.
[[GitHub #98]](https://github.com/ruby/openssl/pull/98)
* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments
'loc' and 'set'.
[[GitHub #94]](https://github.com/ruby/openssl/issues/94)
* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added to replace
#ssl_version= that was built on top of the deprecated OpenSSL C API. Use of
that method and the constant OpenSSL::SSL::SSLContext::METHODS is now
deprecated.
[[GitHub #142]](https://github.com/ruby/openssl/pull/142)
* OpenSSL::X509::Name#to_utf8 is added.
[[GitHub #26]](https://github.com/ruby/openssl/issues/26)
[[GitHub #143]](https://github.com/ruby/openssl/pull/143)
* OpenSSL::X509::{Extension,Attribute,Certificate,CRL,Revoked,Request} can be
compared with == operator.
[[GitHub #161]](https://github.com/ruby/openssl/pull/161)
* TLS Fallback Signaling Cipher Suite Value (SCSV) support is added.
[[GitHub #165]](https://github.com/ruby/openssl/pull/165)
* Build failure with OpenSSL 1.1 built with no-deprecated is fixed.
[[GitHub #160]](https://github.com/ruby/openssl/pull/160)
* OpenSSL::Buffering#write accepts an arbitrary number of arguments.
[[Feature #9323]](https://bugs.ruby-lang.org/issues/9323)
[[GitHub #162]](https://github.com/ruby/openssl/pull/162)
* OpenSSL::PKey::RSA#sign_pss and #verify_pss are added. They perform RSA-PSS
signature and verification.
[[GitHub #75]](https://github.com/ruby/openssl/issues/75)
[[GitHub #76]](https://github.com/ruby/openssl/pull/76)
[[GitHub #169]](https://github.com/ruby/openssl/pull/169)
* OpenSSL::SSL::SSLContext#add_certificate is added.
[[GitHub #167]](https://github.com/ruby/openssl/pull/167)
* OpenSSL::PKey::EC::Point#to_octet_string is added.
OpenSSL::PKey::EC::Point.new can now take String as the second argument.
[[GitHub #177]](https://github.com/ruby/openssl/pull/177)
Version 2.0.8
=============
Bug fixes
---------
* OpenSSL::Cipher#pkcs5_keyivgen raises an error when a negative iteration
count is given.
[[GitHub #184]](https://github.com/ruby/openssl/pull/184)
* Fixed build with LibreSSL 2.7.
[[GitHub #192]](https://github.com/ruby/openssl/issues/192)
[[GitHub #193]](https://github.com/ruby/openssl/pull/193)
Version 2.0.7
=============
Bug fixes
---------
* OpenSSL::Cipher#auth_data= could segfault if called against a non-AEAD cipher.
[[Bug #14024]](https://bugs.ruby-lang.org/issues/14024)
* OpenSSL::X509::Certificate#public_key= (and similar methods) could segfault
when an instance of OpenSSL::PKey::PKey with no public key components is
passed.
[[Bug #14087]](https://bugs.ruby-lang.org/issues/14087)
[[GitHub #168]](https://github.com/ruby/openssl/pull/168)
Version 2.0.6
=============
Bug fixes
---------
* The session_remove_cb set to an OpenSSL::SSL::SSLContext is no longer called
during GC.
* A possible deadlock in OpenSSL::SSL::SSLSocket#sysread is fixed.
[[GitHub #139]](https://github.com/ruby/openssl/pull/139)
* OpenSSL::BN#hash could return an unnormalized fixnum value on Windows.
[[Bug #13877]](https://bugs.ruby-lang.org/issues/13877)
* OpenSSL::SSL::SSLSocket#sysread and #sysread_nonblock set the length of the
destination buffer String to 0 on error.
[[GitHub #153]](https://github.com/ruby/openssl/pull/153)
* Possible deadlock is fixed. This happened only when built with older versions
of OpenSSL (before 1.1.0) or LibreSSL.
[[GitHub #155]](https://github.com/ruby/openssl/pull/155)
Version 2.0.5
=============
......@@ -150,7 +256,7 @@ Notable changes
- A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it
is enabled, and the SNI hostname is also set, the hostname verification on
the server certificate is automatically performed. It is now enabled by
OpenSSL::SSL::Context#set_params.
OpenSSL::SSL::SSLContext#set_params.
[[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60)
Removals
......
......@@ -27,7 +27,7 @@ Alternatively, you can install the gem with `bundler`:
# Gemfile
gem 'openssl'
# or specify git master
gem 'openssl', github: 'ruby/openssl'
gem 'openssl', git: 'https://github.com/ruby/openssl'
```
After doing `bundle install`, you should have the gem installed in your bundle.
......
......@@ -20,7 +20,7 @@ RDoc::Task.new do |rdoc|
rdoc.rdoc_files.include("*.md", "lib/**/*.rb", "ext/**/*.c")
end
task :test => :debug
task :test => [:compile, :debug]
task :debug do
ruby "-I./lib -ropenssl -ve'puts OpenSSL::OPENSSL_VERSION, OpenSSL::OPENSSL_LIBRARY_VERSION'"
end
......@@ -58,11 +58,12 @@ namespace :sync do
paths = [
["ext/openssl/", "ext/openssl/"],
["lib/", "ext/openssl/lib/"],
["sample/", "sample/openssl/"],
["test/fixtures/", "test/openssl/fixtures/"],
["test/utils.rb", "test/openssl/"],
["test/ut_eof.rb", "test/openssl/"],
["test/test_*", "test/openssl/"],
["lib/", "ext/openssl/lib/"],
["sample/", "sample/openssl/"],
["History.md", "ext/openssl/"],
]
paths.each do |src, dst|
......@@ -76,3 +77,5 @@ namespace :sync do
puts "Don't forget to update ext/openssl/depend"
end
end
task :default => :test
......@@ -14,12 +14,11 @@ install:
$Env:openssl_dir = "C:\msys64\mingw64"
}
- ruby -v
- openssl version
- rake install_dependencies
build_script:
- rake -rdevkit compile -- --with-openssl-dir=%openssl_dir%
- rake -rdevkit compile -- --with-openssl-dir=%openssl_dir% --enable-debug
test_script:
- rake test
- rake test OSSL_MDEBUG=1
deploy: off
environment:
matrix:
......
......@@ -3,11 +3,10 @@ compile: &defaults
environment:
RUBY_VERSION:
OPENSSL_VERSION:
MDEBUG:
command: rake compile
test:
<<: *defaults
command: rake compile test
command: rake compile test OSSL_MDEBUG=1 -- --enable-debug
debug:
<<: *defaults
command: /bin/bash
......@@ -3,9 +3,6 @@ module OpenSSL
def self.deprecated_warning_flag
unless flag = (@deprecated_warning_flag ||= nil)
if try_compile("", flag = "-Werror=deprecated-declarations")
if /darwin/ =~ RUBY_PLATFORM and with_config("broken-apple-openssl")
flag = "-Wno-deprecated-declarations"
end
$warnflags << " #{flag}"
else
flag = ""
......
......@@ -91,30 +91,19 @@ unless result
unless find_openssl_library
Logging::message "=== Checking for required stuff failed. ===\n"
Logging::message "Makefile wasn't created. Fix the errors above.\n"
exit 1
raise "OpenSSL library could not be found. You might want to use " \
"--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
"is installed."
end
end
result = checking_for("OpenSSL version is 0.9.8 or later") {
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h")
}
unless result
raise "OpenSSL 0.9.8 or later required."
end
if /darwin/ =~ RUBY_PLATFORM and !OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h")
raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')"
unless checking_for("OpenSSL version is 1.0.1 or later") {
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") }
raise "OpenSSL >= 1.0.1 or LibreSSL is required"
end
Logging::message "=== Checking for OpenSSL features... ===\n"
# compile options
# SSLv2 and SSLv3 may be removed in future versions of OpenSSL, and even macros
# like OPENSSL_NO_SSL2 may not be defined.
have_func("SSLv2_method")
have_func("SSLv3_method")
have_func("TLSv1_1_method")
have_func("TLSv1_2_method")
have_func("RAND_egd")
engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil
cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni}
......@@ -122,30 +111,6 @@ engines.each { |name|
OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h")
}
# added in 0.9.8X
have_func("EVP_CIPHER_CTX_new")
have_func("EVP_CIPHER_CTX_free")
OpenSSL.check_func_or_macro("SSL_CTX_clear_options", "openssl/ssl.h")
# added in 1.0.0
have_func("ASN1_TIME_adj")
have_func("EVP_CIPHER_CTX_copy")
have_func("EVP_PKEY_base_id")
have_func("HMAC_CTX_copy")
have_func("PKCS5_PBKDF2_HMAC")
have_func("X509_NAME_hash_old")
have_func("X509_STORE_CTX_get0_current_crl")
have_func("X509_STORE_set_verify_cb")
have_func("i2d_ASN1_SET_ANY")
have_func("SSL_SESSION_cmp") # removed
OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h")
have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h")
have_func("EVP_PKEY_get0")
# added in 1.0.1
have_func("SSL_CTX_set_next_proto_select_cb")
have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION")
# added in 1.0.2
have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup")
......@@ -157,8 +122,11 @@ OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h")
have_func("SSL_is_server")
# added in 1.1.0
if !have_struct_member("SSL", "ctx", "openssl/ssl.h") ||
try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x2070000fL", "openssl/opensslv.h")
$defs.push("-DHAVE_OPAQUE_OPENSSL")
end
have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API")
have_struct_member("SSL", "ctx", "openssl/ssl.h") || $defs.push("-DHAVE_OPAQUE_OPENSSL")
have_func("BN_GENCB_new")
have_func("BN_GENCB_free")
have_func("BN_GENCB_get_arg")
......@@ -189,6 +157,7 @@ OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h")
have_func("SSL_CTX_get_security_level")
have_func("X509_get0_notBefore")
have_func("SSL_SESSION_get_protocol_version")
have_func("EVP_PBE_scrypt")
Logging::message "=== Checking done. ===\n"
......
......@@ -20,73 +20,6 @@
#include "openssl_missing.h"
/* added in 0.9.8X */
#if !defined(HAVE_EVP_CIPHER_CTX_NEW)
EVP_CIPHER_CTX *
ossl_EVP_CIPHER_CTX_new(void)
{
EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
if (!ctx)
return NULL;
EVP_CIPHER_CTX_init(ctx);
return ctx;
}
#endif
#if !defined(HAVE_EVP_CIPHER_CTX_FREE)
void
ossl_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
{
if (ctx) {
EVP_CIPHER_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
#endif
/* added in 1.0.0 */
#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
ossl_EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
{
memcpy(out, in, sizeof(EVP_CIPHER_CTX));
#if !defined(OPENSSL_NO_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(OPENSSL_NO_HMAC)
#if !defined(HAVE_HMAC_CTX_COPY)
int
ossl_HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
{
if (!out || !in)
return 0;
memcpy(out, in, sizeof(HMAC_CTX));
EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
return 1;
}
#endif /* HAVE_HMAC_CTX_COPY */
#endif /* NO_HMAC */
/* added in 1.0.2 */
#if !defined(OPENSSL_NO_EC)
#if !defined(HAVE_EC_CURVE_NIST2NID)
......
......@@ -12,53 +12,6 @@
#include "ruby/config.h"
/* added in 0.9.8X */
#if !defined(HAVE_EVP_CIPHER_CTX_NEW)
EVP_CIPHER_CTX *ossl_EVP_CIPHER_CTX_new(void);
# define EVP_CIPHER_CTX_new ossl_EVP_CIPHER_CTX_new
#endif
#if !defined(HAVE_EVP_CIPHER_CTX_FREE)
void ossl_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *);
# define EVP_CIPHER_CTX_free ossl_EVP_CIPHER_CTX_free
#endif
#if !defined(HAVE_SSL_CTX_CLEAR_OPTIONS)
# define SSL_CTX_clear_options(ctx, op) ((ctx)->options &= ~(op))
#endif
/* added in 1.0.0 */
#if !defined(HAVE_EVP_PKEY_BASE_ID)
# define EVP_PKEY_base_id(pkey) EVP_PKEY_type((pkey)->type)
#endif
#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
int ossl_EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *, const EVP_CIPHER_CTX *);
# define EVP_CIPHER_CTX_copy ossl_EVP_CIPHER_CTX_copy
#endif
#if !defined(HAVE_HMAC_CTX_COPY)
int ossl_HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
# define HMAC_CTX_copy ossl_HMAC_CTX_copy
#endif
#if !defined(HAVE_X509_STORE_CTX_GET0_CURRENT_CRL)
# define X509_STORE_CTX_get0_current_crl(x) ((x)->current_crl)
#endif
#if !defined(HAVE_X509_STORE_SET_VERIFY_CB)
# define X509_STORE_set_verify_cb X509_STORE_set_verify_cb_func
#endif
#if !defined(HAVE_I2D_ASN1_SET_ANY)
# define i2d_ASN1_SET_ANY(sk, x) i2d_ASN1_SET_OF_ASN1_TYPE((sk), (x), \
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0)
#endif
#if !defined(HAVE_EVP_PKEY_GET0)
# define EVP_PKEY_get0(pk) (pk->pkey.ptr)
#endif
/* added in 1.0.2 */
#if !defined(OPENSSL_NO_EC)
#if !defined(HAVE_EC_CURVE_NIST2NID)
......@@ -245,7 +198,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
#undef IMPL_KEY_ACCESSOR3
#endif /* HAVE_OPAQUE_OPENSSL */
#if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG)
#if !defined(EVP_CTRL_AEAD_GET_TAG)
# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
# define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
......@@ -256,6 +209,10 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
# define X509_get0_notAfter(x) X509_get_notAfter(x)
# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x)
# define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x)
# define X509_set1_notBefore(x, t) X509_set_notBefore(x, t)
# define X509_set1_notAfter(x, t) X509_set_notAfter(x, t)
# define X509_CRL_set1_lastUpdate(x, t) X509_CRL_set_lastUpdate(x, t)
# define X509_CRL_set1_nextUpdate(x, t) X509_CRL_set_nextUpdate(x, t)
#endif
#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION)
......
......@@ -92,22 +92,40 @@ OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
OSSL_IMPL_SK2ARY(x509name, X509_NAME)
static VALUE
ossl_str_new(int size)
ossl_str_new_i(VALUE size)
{
return rb_str_new(0, size);
return rb_str_new(NULL, (long)size);
}
VALUE
ossl_str_new(const char *ptr, long len, int *pstate)
{
VALUE str;
int state;
str = rb_protect(ossl_str_new_i, len, &state);
if (pstate)
*pstate = state;
if (state) {
if (!pstate)
rb_set_errinfo(Qnil);
return Qnil;
}
if (ptr)
memcpy(RSTRING_PTR(str), ptr, len);
return str;
}
VALUE
ossl_buf2str(char *buf, int len)
{
VALUE str;
int status = 0;
int state;
str = rb_protect((VALUE (*)(VALUE))ossl_str_new, len, &status);
if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
str = ossl_str_new(buf, len, &state);
OPENSSL_free(buf);
if(status) rb_jump_tag(status);
if (state)
rb_jump_tag(state);
return str;
}
......@@ -220,7 +238,7 @@ VALUE eOSSLError;
/*
* Convert to DER string
*/
ID ossl_s_to_der;
static ID ossl_s_to_der;
VALUE
ossl_to_der(VALUE obj)
......@@ -248,18 +266,15 @@ static VALUE
ossl_make_error(VALUE exc, const char *fmt, va_list args)
{
VALUE str = Qnil;
const char *msg;
long e;
unsigned long e;
e = ERR_peek_last_error();
if (fmt) {
str = rb_vsprintf(fmt, args);
}
e = ERR_peek_last_error();
if (e) {
if (dOSSL == Qtrue) /* FULL INFO */
msg = ERR_error_string(e, NULL);
else
msg = ERR_reason_error_string(e);
const char *msg = ERR_reason_error_string(e);
if (NIL_P(str)) {
if (msg) str = rb_str_new_cstr(msg);
}
......@@ -267,8 +282,8 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
if (RSTRING_LEN(str)) rb_str_cat2(str, ": ");
rb_str_cat2(str, msg ? msg : "(null)");
}
ossl_clear_error();
}
ossl_clear_error();
if (NIL_P(str)) str = rb_str_new(0, 0);
return rb_exc_new3(exc, str);
......@@ -319,7 +334,8 @@ ossl_clear_error(void)
*
* See any remaining errors held in queue.
*
* Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
* Any errors you see here are probably due to a bug in Ruby's OpenSSL
* implementation.
*/
VALUE
ossl_get_errors(void)
......@@ -381,6 +397,23 @@ ossl_debug_set(VALUE self, VALUE val)
return val;
}
/*
* call-seq
* OpenSSL.fips_mode -> true | false
*/
static VALUE
ossl_fips_mode_get(VALUE self)
{
#ifdef OPENSSL_FIPS
VALUE enabled;
enabled = FIPS_mode() ? Qtrue : Qfalse;
return enabled;
#else
return Qfalse;
#endif
}
/*
* call-seq:
* OpenSSL.fips_mode = boolean -> boolean
......@@ -414,44 +447,123 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
#endif
}
#if defined(OSSL_DEBUG)
#if !defined(LIBRESSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
defined(CRYPTO_malloc_debug_init))
/*
* call-seq:
* OpenSSL.mem_check_start -> nil
*
* Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
* allocations. See also OpenSSL.print_mem_leaks.
*
* This is available only when built with a capable OpenSSL and --enable-debug
* configure option.
*/
static VALUE
mem_check_start(VALUE self)
{
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
return Qnil;
}
/*
* call-seq:
* OpenSSL.print_mem_leaks -> true | false
*
* For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
* Prints detected memory leaks to standard error. This cleans the global state
* up thus you cannot use any methods of the library after calling this.
*
* Returns +true+ if leaks detected, +false+ otherwise.
*
* This is available only when built with a capable OpenSSL and --enable-debug
* configure option.
*
* === Example
* OpenSSL.mem_check_start
* NOT_GCED = OpenSSL::PKey::RSA.new(256)
*
* END {
* GC.start
* OpenSSL.print_mem_leaks # will print the leakage
* }
*/
static VALUE
print_mem_leaks(VALUE self)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000
int ret;
#endif
BN_CTX_free(ossl_bn_ctx);
ossl_bn_ctx = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x10100000
ret = CRYPTO_mem_leaks_fp(stderr);
if (ret < 0)
ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp");
return ret ? Qfalse : Qtrue;
#else
CRYPTO_mem_leaks_fp(stderr);
return Qnil;
#endif
}
#endif
#endif
#if !defined(HAVE_OPENSSL_110_THREADING_API)
/**
* Stores locks needed for OpenSSL thread safety
*/
static rb_nativethread_lock_t *ossl_locks;
struct CRYPTO_dynlock_value {
rb_nativethread_lock_t lock;
rb_nativethread_id_t owner;
size_t count;
};
static void
ossl_lock_unlock(int mode, rb_nativethread_lock_t *lock)
ossl_lock_init(struct CRYPTO_dynlock_value *l)
{
if (mode & CRYPTO_LOCK) {
rb_nativethread_lock_lock(lock);
} else {
rb_nativethread_lock_unlock(lock);
}
rb_nativethread_lock_initialize(&l->lock);
l->count = 0;
}
static void
ossl_lock_callback(int mode, int type, const char *file, int line)
ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l)
{
ossl_lock_unlock(mode, &ossl_locks[type]);
if (mode & CRYPTO_LOCK) {
/* TODO: rb_nativethread_id_t is not necessarily compared with ==. */
rb_nativethread_id_t tid = rb_nativethread_self();
if (l->count && l->owner == tid) {
l->count++;
return;
}
rb_nativethread_lock_lock(&l->lock);
l->owner = tid;
l->count = 1;
} else {
if (!--l->count)
rb_nativethread_lock_unlock(&l->lock);
}
}
struct CRYPTO_dynlock_value {
rb_nativethread_lock_t lock;
};
static struct CRYPTO_dynlock_value *
ossl_dyn_create_callback(const char *file, int line)
{
struct CRYPTO_dynlock_value *dynlock = (struct CRYPTO_dynlock_value *)OPENSSL_malloc((int)sizeof(struct CRYPTO_dynlock_value));
rb_nativethread_lock_initialize(&dynlock->lock);
/* Do not use xmalloc() here, since it may raise NoMemoryError */
struct CRYPTO_dynlock_value *dynlock =
OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));
if (dynlock)
ossl_lock_init(dynlock);
return dynlock;
}
static void
ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
{
ossl_lock_unlock(mode, &l->lock);
ossl_lock_unlock(mode, l);
}
static void
......@@ -461,41 +573,30 @@ ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int
OPENSSL_free(l);
}
#ifdef HAVE_CRYPTO_THREADID_PTR
static void ossl_threadid_func(CRYPTO_THREADID *id)
{
/* register native thread id */
CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self());
}