aboutsummaryrefslogtreecommitdiffstats
path: root/ext/openssl
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-08-09 16:50:08 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-08-09 16:50:30 +0900
commit580c6d4a51d7a8713e46b06474341e1297d4de13 (patch)
tree2f12292b98ccafd30ec5df61f77376494471188c /ext/openssl
parent714f0d8f2d2b35075158d870e7e8298e31d8c409 (diff)
parent3292933e67790dddfc28dcaba3ed08c066216d40 (diff)
downloadruby-openssl-580c6d4a51d7a8713e46b06474341e1297d4de13.tar.gz
Merge branch 'master' into topic/doc-work
Diffstat (limited to 'ext/openssl')
-rw-r--r--ext/openssl/openssl_missing.h1
-rw-r--r--ext/openssl/ossl.c76
-rw-r--r--ext/openssl/ossl.h9
-rw-r--r--ext/openssl/ossl_asn1.c6
-rw-r--r--ext/openssl/ossl_bio.c4
-rw-r--r--ext/openssl/ossl_cipher.c94
-rw-r--r--ext/openssl/ossl_digest.c16
-rw-r--r--ext/openssl/ossl_engine.c1
-rw-r--r--ext/openssl/ossl_pkcs12.c26
-rw-r--r--ext/openssl/ossl_pkey.c20
-rw-r--r--ext/openssl/ossl_pkey.h2
-rw-r--r--ext/openssl/ossl_pkey_dsa.c17
-rw-r--r--ext/openssl/ossl_pkey_rsa.c4
-rw-r--r--ext/openssl/ossl_ssl.c103
-rw-r--r--ext/openssl/ossl_ssl_session.c21
-rw-r--r--ext/openssl/ossl_x509attr.c20
-rw-r--r--ext/openssl/ossl_x509ext.c20
-rw-r--r--ext/openssl/ossl_x509name.c20
-rw-r--r--ext/openssl/ossl_x509revoked.c20
-rw-r--r--ext/openssl/ossl_x509store.c18
20 files changed, 355 insertions, 143 deletions
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 769c7c2d..d2fdce16 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -231,6 +231,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
#if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !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
#endif
#endif /* _OSSL_OPENSSL_MISSING_H_ */
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 88e0e79a..bbd9af3b 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -9,6 +9,7 @@
*/
#include "ossl.h"
#include <stdarg.h> /* for ossl_raise */
+#include <ruby/thread_native.h> /* for OpenSSL < 1.1.0 locks */
/*
* String to HEXString conversion
@@ -77,7 +78,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); \
} \
@@ -136,7 +137,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);
@@ -242,54 +243,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;
@@ -511,7 +512,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
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 2317fa8b..c15a25bc 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -154,14 +154,7 @@ void ossl_clear_error(void);
extern int ossl_store_ctx_ex_verify_cb_idx;
extern int ossl_store_ex_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 *);
+int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
/*
* String to DER String
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index eb48aa5b..5fea9a2f 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -383,7 +383,7 @@ decode_int(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
+ ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
(VALUE)ai, &status);
ASN1_INTEGER_free(ai);
if(status) rb_jump_tag(status);
@@ -423,7 +423,7 @@ decode_enum(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
+ ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
(VALUE)ai, &status);
ASN1_ENUMERATED_free(ai);
if(status) rb_jump_tag(status);
@@ -485,7 +485,7 @@ decode_time(unsigned char* der, long length)
p = der;
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
+ ret = rb_protect((VALUE (*)(VALUE))asn1time_to_time,
(VALUE)time, &status);
ASN1_TIME_free(time);
if(status) rb_jump_tag(status);
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index cd258264..feaf2296 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -51,7 +51,7 @@ BIO *
ossl_protect_obj2bio(VALUE obj, int *status)
{
BIO *ret = NULL;
- ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status);
+ ret = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, obj, status);
return ret;
}
@@ -70,7 +70,7 @@ ossl_membio2str0(BIO *bio)
VALUE
ossl_protect_membio2str(BIO *bio, int *status)
{
- return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status);
+ return rb_protect((VALUE (*)(VALUE))ossl_membio2str0, (VALUE)bio, status);
}
VALUE
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 76b0aae9..83c43904 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -331,25 +331,23 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
const unsigned char *in, long in_len)
{
int out_part_len;
+ int limit = INT_MAX / 2 + 1;
long out_len = 0;
-#define UPDATE_LENGTH_LIMIT INT_MAX
-
-#if SIZEOF_LONG > UPDATE_LENGTH_LIMIT
- if (in_len > UPDATE_LENGTH_LIMIT) {
- const int in_part_len = (UPDATE_LENGTH_LIMIT / 2 + 1) & ~1;
- do {
- if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
- &out_part_len, in, in_part_len))
- return 0;
- out_len += out_part_len;
- in += in_part_len;
- } while ((in_len -= in_part_len) > UPDATE_LENGTH_LIMIT);
- }
-#endif
- if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
- &out_part_len, in, (int)in_len))
- return 0;
- if (out_len_ptr) *out_len_ptr = out_len += out_part_len;
+
+ do {
+ int in_part_len = in_len > limit ? limit : (int)in_len;
+
+ if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
+ &out_part_len, in, in_part_len))
+ return 0;
+
+ out_len += out_part_len;
+ in += in_part_len;
+ } while ((in_len -= limit) > 0);
+
+ if (out_len_ptr)
+ *out_len_ptr = out_len;
+
return 1;
}
@@ -499,12 +497,17 @@ static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
EVP_CIPHER_CTX *ctx;
- int iv_len;
+ int iv_len = 0;
StringValue(iv);
GetCipher(self, ctx);
- iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
+ if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+#endif
+ if (!iv_len)
+ iv_len = EVP_CIPHER_CTX_iv_length(ctx);
if (RSTRING_LEN(iv) != iv_len)
ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
@@ -638,11 +641,42 @@ ossl_cipher_is_authenticated(VALUE self)
return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
}
+
+/*
+ * call-seq:
+ * cipher.iv_len = integer -> integer
+ *
+ * Sets the IV/nonce length of the Cipher. Normally block ciphers don't allow
+ * changing the IV length, but some make use of IV for 'nonce'. You may need
+ * this for interoperability with other applications.
+ */
+static VALUE
+ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
+{
+ int len = NUM2INT(iv_length);
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+ if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "cipher does not support AEAD");
+
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL))
+ ossl_raise(eCipherError, "unable to set IV length");
+
+ /*
+ * EVP_CIPHER_CTX_iv_length() returns the default length. So we need to save
+ * the length somewhere. Luckily currently we aren't using app_data.
+ */
+ EVP_CIPHER_CTX_set_app_data(ctx, (void *)(VALUE)len);
+
+ return iv_length;
+}
#else
#define ossl_cipher_set_auth_data rb_f_notimplement
#define ossl_cipher_get_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag rb_f_notimplement
#define ossl_cipher_is_authenticated rb_f_notimplement
+#define ossl_cipher_set_iv_length rb_f_notimplement
#endif
/*
@@ -708,13 +742,30 @@ ossl_cipher_set_padding(VALUE self, VALUE padding)
* Returns the key length in bytes of the Cipher.
*/
CIPHER_0ARG_INT(key_length)
+
/*
* call-seq:
* cipher.iv_len -> integer
*
* Returns the expected length in bytes for an IV for this Cipher.
*/
-CIPHER_0ARG_INT(iv_length)
+static VALUE
+ossl_cipher_iv_length(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+ int len = 0;
+
+ GetCipher(self, ctx);
+#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
+ if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+#endif
+ if (!len)
+ len = EVP_CIPHER_CTX_iv_length(ctx);
+
+ return INT2NUM(len);
+}
+
/*
* call-seq:
* cipher.block_size -> integer
@@ -953,6 +1004,7 @@ Init_ossl_cipher(void)
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_set_iv_length, 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/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 317083fe..f9451220 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -203,7 +203,9 @@ ossl_digest_update(VALUE self, VALUE data)
StringValue(data);
GetDigest(self, ctx);
- EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
+
+ if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
+ ossl_raise(eDigestError, "EVP_DigestUpdate");
return self;
}
@@ -218,19 +220,21 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
VALUE str;
-
- rb_scan_args(argc, argv, "01", &str);
+ int out_len;
GetDigest(self, ctx);
+ rb_scan_args(argc, argv, "01", &str);
+ out_len = EVP_MD_CTX_size(ctx);
if (NIL_P(str)) {
- str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
+ str = rb_str_new(NULL, out_len);
} else {
StringValue(str);
- rb_str_resize(str, EVP_MD_CTX_size(ctx));
+ rb_str_resize(str, out_len);
}
- EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL);
+ if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
+ ossl_raise(eDigestError, "EVP_DigestFinal_ex");
return str;
}
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 1da8430f..f4863b36 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -543,6 +543,7 @@ Init_ossl_engine(void)
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_undef_method(cEngine, "initialize_copy");
rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index 43fc5e51..33ad08a7 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -65,6 +65,25 @@ ossl_pkcs12_s_allocate(VALUE klass)
return obj;
}
+static VALUE
+ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
+{
+ PKCS12 *p12, *p12_old, *p12_new;
+
+ rb_check_frozen(self);
+ GetPKCS12(self, p12_old);
+ SafeGetPKCS12(other, p12);
+
+ p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
+ if (!p12_new)
+ ossl_raise(ePKCS12Error, "ASN1_dup");
+
+ SetPKCS12(self, p12_new);
+ PKCS12_free(p12_old);
+
+ return self;
+}
+
/*
* call-seq:
* PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
@@ -171,14 +190,14 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
ossl_raise(ePKCS12Error, "PKCS12_parse");
ERR_pop_to_mark();
- pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
+ 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);
+ 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);
+ rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st);
if(st) goto err;
}
@@ -231,6 +250,7 @@ Init_ossl_pkcs12(void)
rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
+ rb_define_copy_func(cPKCS12, ossl_pkcs12_initialize_copy);
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);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 2058af74..7b237337 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -15,7 +15,7 @@
VALUE mPKey;
VALUE cPKey;
VALUE ePKeyError;
-ID id_private_q;
+static ID id_private_q;
/*
* callback for generating keys
@@ -197,20 +197,6 @@ DupPKeyPtr(VALUE obj)
return pkey;
}
-EVP_PKEY *
-DupPrivPKeyPtr(VALUE obj)
-{
- EVP_PKEY *pkey;
-
- if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) {
- ossl_raise(rb_eArgError, "Private key is needed.");
- }
- SafeGetPKey(obj, pkey);
- EVP_PKEY_up_ref(pkey);
-
- return pkey;
-}
-
/*
* Private
*/
@@ -272,9 +258,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
VALUE str;
int result;
- if (rb_funcallv(self, id_private_q, 0, NULL) != Qtrue)
- ossl_raise(rb_eArgError, "Private key is needed.");
- GetPKey(self, pkey);
+ pkey = GetPrivPKeyPtr(self);
md = GetDigestPtr(digest);
StringValue(data);
str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 1f68352c..218f2ebb 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -13,7 +13,6 @@
extern VALUE mPKey;
extern VALUE cPKey;
extern VALUE ePKeyError;
-extern ID id_private_q;
extern const rb_data_type_t ossl_evp_pkey_type;
#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
@@ -53,7 +52,6 @@ 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);
/*
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 7c08620c..db103cb6 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -95,8 +95,6 @@ ossl_dsa_new(EVP_PKEY *pkey)
struct dsa_blocking_gen_arg {
DSA *dsa;
int size;
- unsigned char* seed;
- int seed_len;
int *counter;
unsigned long *h;
BN_GENCB *cb;
@@ -107,7 +105,8 @@ static void *
dsa_blocking_gen(void *arg)
{
struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
- gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
+ gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0,
+ gen->counter, gen->h, gen->cb);
return 0;
}
@@ -118,13 +117,9 @@ dsa_generate(int size)
struct dsa_blocking_gen_arg gen_arg;
DSA *dsa = DSA_new();
BN_GENCB *cb = BN_GENCB_new();
- unsigned char seed[20];
- int seed_len = 20, counter;
+ int counter;
unsigned long h;
- if (RAND_bytes(seed, seed_len) <= 0)
- return NULL;
-
if (!dsa || !cb) {
DSA_free(dsa);
BN_GENCB_free(cb);
@@ -136,8 +131,6 @@ dsa_generate(int size)
BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
gen_arg.dsa = dsa;
gen_arg.size = size;
- gen_arg.seed = seed;
- gen_arg.seed_len = seed_len;
gen_arg.counter = &counter;
gen_arg.h = &h;
gen_arg.cb = cb;
@@ -387,14 +380,14 @@ static VALUE
ossl_dsa_to_der(VALUE self)
{
DSA *dsa;
- int (*i2d_func)_((DSA*, unsigned char**));
+ int (*i2d_func)(DSA *, unsigned char **);
unsigned char *p;
long len;
VALUE str;
GetDSA(self, dsa);
if(DSA_HAS_PRIVATE(dsa))
- i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
+ i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
else
i2d_func = i2d_DSA_PUBKEY;
if((len = i2d_func(dsa, NULL)) <= 0)
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 18507ebb..e003d9ff 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -383,7 +383,7 @@ static VALUE
ossl_rsa_to_der(VALUE self)
{
RSA *rsa;
- int (*i2d_func)_((const RSA*, unsigned char**));
+ int (*i2d_func)(const RSA *, unsigned char **);
unsigned char *p;
long len;
VALUE str;
@@ -392,7 +392,7 @@ ossl_rsa_to_der(VALUE self)
if (RSA_HAS_PRIVATE(rsa))
i2d_func = i2d_RSAPrivateKey;
else
- i2d_func = (int (*)(const RSA*, unsigned char**))i2d_RSA_PUBKEY;
+ i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
if((len = i2d_func(rsa, NULL)) <= 0)
ossl_raise(eRSAError, NULL);
str = rb_str_new(0, len);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 5044c6d1..a443c055 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -64,18 +64,15 @@ static VALUE eSSLErrorWaitWritable;
#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
#define ossl_sslctx_get_tmp_ecdh_cb(o) rb_iv_get((o),"@tmp_ecdh_callback")
#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
+#define ossl_sslctx_get_verify_hostname(o) rb_iv_get((o),"@verify_hostname")
#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_x509(o) rb_iv_get((o),"@x509")
-#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
#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_hostname_v(o,v) rb_iv_set((o),"@hostname",(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))
#define ossl_ssl_set_tmp_ecdh(o,v) rb_iv_set((o),"@tmp_ecdh",(v))
@@ -225,28 +222,30 @@ ossl_call_client_cert_cb(VALUE obj)
{
VALUE cb, ary, cert, key;
- cb = rb_funcall(obj, rb_intern("client_cert_cb"), 0);
- if (NIL_P(cb)) return Qfalse;
+ cb = ossl_sslctx_get_client_cert_cb(ossl_ssl_get_ctx(obj));
+ if (NIL_P(cb))
+ return Qnil;
+
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);
+ GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
- return Qtrue;
+ return rb_ary_new3(2, cert, key);
}
static int
ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
- VALUE obj, success;
+ VALUE obj, ret;
obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- success = rb_protect(ossl_call_client_cert_cb, obj, NULL);
- if (!RTEST(success)) return 0;
- *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
- *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
+ ret = rb_protect(ossl_call_client_cert_cb, obj, NULL);
+ if (NIL_P(ret))
+ return 0;
+
+ *x509 = DupX509CertPtr(RARRAY_AREF(ret, 0));
+ *pkey = DupPKeyPtr(RARRAY_AREF(ret, 1));
return 1;
}
@@ -319,16 +318,50 @@ ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
}
#endif
+static VALUE
+call_verify_certificate_identity(VALUE ctx_v)
+{
+ X509_STORE_CTX *ctx = (X509_STORE_CTX *)ctx_v;
+ SSL *ssl;
+ VALUE ssl_obj, hostname, cert_obj;
+
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ hostname = rb_attr_get(ssl_obj, rb_intern("@hostname"));
+
+ if (!RTEST(hostname)) {
+ rb_warning("verify_hostname requires hostname to be set");
+ return Qtrue;
+ }
+
+ cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+ return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2,
+ cert_obj, hostname);
+}
+
static int
ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
- VALUE cb;
+ VALUE cb, ssl_obj, verify_hostname, ret;
SSL *ssl;
+ int status;
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_store_ctx_ex_verify_cb_idx, (void *)cb);
- return ossl_verify_cb(preverify_ok, ctx);
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ verify_hostname = ossl_sslctx_get_verify_hostname(ossl_ssl_get_ctx(ssl_obj));
+
+ if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
+ !X509_STORE_CTX_get_error_depth(ctx)) {
+ ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
+ if (status) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
+ return 0;
+ }
+ preverify_ok = ret == Qtrue;
+ }
+
+ return ossl_verify_cb_call(cb, preverify_ok, ctx);
}
static VALUE
@@ -464,7 +497,7 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
rb_ary_push(ary, sslctx_obj);
rb_ary_push(ary, sess_obj);
- rb_protect((VALUE(*)_((VALUE)))ossl_call_session_remove_cb, ary, &state);
+ rb_protect(ossl_call_session_remove_cb, ary, &state);
if (state) {
/*
the SSL_CTX is frozen, nowhere to save state.
@@ -540,7 +573,7 @@ ssl_servername_cb(SSL *ssl, int *ad, void *arg)
rb_ary_push(ary, ssl_obj);
rb_ary_push(ary, rb_str_new2(servername));
- rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state);
+ rb_protect(ossl_call_servername_cb, ary, &state);
if (state) {
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
return SSL_TLSEXT_ERR_ALERT_FATAL;
@@ -624,8 +657,7 @@ ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *out
static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
{
- VALUE sslctx_obj = (VALUE) arg;
- VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols");
+ VALUE protocols = (VALUE)arg;
*out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols);
@@ -776,7 +808,7 @@ ossl_sslctx_setup(VALUE self)
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 */
+ key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
if (cert && key) {
if (!SSL_CTX_use_certificate(ctx, cert)) {
/* Adds a ref => Safe to FREE */
@@ -835,8 +867,8 @@ ossl_sslctx_setup(VALUE self)
#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
val = rb_iv_get(self, "@npn_protocols");
if (!NIL_P(val)) {
- rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
+ VALUE encoded = ssl_encode_npn_protocols(val);
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
OSSL_Debug("SSL NPN advertise callback added");
}
if (RTEST(rb_iv_get(self, "@npn_select_cb"))) {
@@ -1744,7 +1776,13 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
if (ssl_started(ssl)) {
for (;;){
- nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
+ int num = RSTRING_LENINT(str);
+
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
+ if (num == 0)
+ goto end;
+
+ nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE:
goto end;
@@ -2223,6 +2261,7 @@ Init_ossl_ssl(void)
*/
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
+ rb_undef_method(cSSLContext, "initialize_copy");
/*
* Context certificate
@@ -2278,11 +2317,20 @@ Init_ossl_ssl(void)
* +store_context+ is an OpenSSL::X509::StoreContext containing the
* context used for certificate verification.
*
- * If the callback returns false verification is stopped.
+ * If the callback returns false, the chain verification is immediately
+ * stopped and a bad_certificate alert is then sent.
*/
rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
/*
+ * Whether to check the server certificate is valid for the hostname.
+ *
+ * In order to make this work, verify_mode must be set to VERIFY_PEER and
+ * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
+ */
+ rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse);
+
+ /*
* An OpenSSL::X509::Store used for certificate verification
*/
rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
@@ -2538,6 +2586,7 @@ Init_ossl_ssl(void)
rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
+ rb_undef_method(cSSLSocket, "initialize_copy");
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index 81d5c4e4..6ff670d5 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -73,6 +73,26 @@ static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
return self;
}
+static VALUE
+ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
+{
+ SSL_SESSION *sess, *sess_other, *sess_new;
+
+ rb_check_frozen(self);
+ sess = RTYPEDDATA_DATA(self); /* XXX */
+ SafeGetSSLSession(other, sess_other);
+
+ sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION,
+ (char *)sess_other);
+ if (!sess_new)
+ ossl_raise(eSSLSession, "ASN1_dup");
+
+ RTYPEDDATA_DATA(self) = sess_new;
+ SSL_SESSION_free(sess);
+
+ return self;
+}
+
#if HAVE_SSL_SESSION_CMP == 0
int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
{
@@ -317,6 +337,7 @@ void Init_ossl_ssl_session(void)
rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
+ rb_define_copy_func(cSSLSession, ossl_ssl_session_initialize_copy);
rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index fc1690ce..6b7f9da4 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -130,6 +130,25 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_x509attr_initialize_copy(VALUE self, VALUE other)
+{
+ X509_ATTRIBUTE *attr, *attr_other, *attr_new;
+
+ rb_check_frozen(self);
+ GetX509Attr(self, attr);
+ SafeGetX509Attr(other, attr_other);
+
+ attr_new = X509_ATTRIBUTE_dup(attr_other);
+ if (!attr_new)
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
+
+ SetX509Attr(self, attr_new);
+ X509_ATTRIBUTE_free(attr);
+
+ return self;
+}
+
/*
* call-seq:
* attr.oid = string => string
@@ -300,6 +319,7 @@ Init_ossl_x509attr(void)
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_copy_func(cX509Attr, ossl_x509attr_initialize_copy);
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);
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 48daa6bb..021cc8ab 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -323,6 +323,25 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
}
static VALUE
+ossl_x509ext_initialize_copy(VALUE self, VALUE other)
+{
+ X509_EXTENSION *ext, *ext_other, *ext_new;
+
+ rb_check_frozen(self);
+ GetX509Ext(self, ext);
+ SafeGetX509Ext(other, ext_other);
+
+ ext_new = X509_EXTENSION_dup(ext_other);
+ if (!ext_new)
+ ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
+
+ SetX509Ext(self, ext_new);
+ X509_EXTENSION_free(ext);
+
+ return self;
+}
+
+static VALUE
ossl_x509ext_set_oid(VALUE self, VALUE oid)
{
X509_EXTENSION *ext;
@@ -475,6 +494,7 @@ Init_ossl_x509ext(void)
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_copy_func(cX509Ext, ossl_x509ext_initialize_copy);
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);
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index a99be7ee..f8cbbdb9 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -181,6 +181,25 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_x509name_initialize_copy(VALUE self, VALUE other)
+{
+ X509_NAME *name, *name_other, *name_new;
+
+ rb_check_frozen(self);
+ GetX509Name(self, name);
+ SafeGetX509Name(other, name_other);
+
+ name_new = X509_NAME_dup(name_other);
+ if (!name_new)
+ ossl_raise(eX509NameError, "X509_NAME_dup");
+
+ SetX509Name(self, name_new);
+ X509_NAME_free(name);
+
+ return self;
+}
+
/*
* call-seq:
* name.add_entry(oid, value [, type]) => self
@@ -464,6 +483,7 @@ Init_ossl_x509name(void)
rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
+ rb_define_copy_func(cX509Name, ossl_x509name_initialize_copy);
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);
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 87a9b323..6f170077 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -110,6 +110,25 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
}
static VALUE
+ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
+{
+ X509_REVOKED *rev, *rev_other, *rev_new;
+
+ rb_check_frozen(self);
+ GetX509Rev(self, rev);
+ SafeGetX509Rev(other, rev_other);
+
+ rev_new = X509_REVOKED_dup(rev_other);
+ if (!rev_new)
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
+
+ SetX509Rev(self, rev_new);
+ X509_REVOKED_free(rev);
+
+ return self;
+}
+
+static VALUE
ossl_x509revoked_get_serial(VALUE self)
{
X509_REVOKED *rev;
@@ -239,6 +258,7 @@ Init_ossl_x509revoked(void)
rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc);
rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1);
+ rb_define_copy_func(cX509Rev, ossl_x509revoked_initialize_copy);
rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0);
rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1);
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index f3d6bf3b..10bae172 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -106,6 +106,20 @@ DupX509StorePtr(VALUE obj)
/*
* Private functions
*/
+static int
+x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ VALUE proc;
+
+ 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)
+ return ok;
+
+ return ossl_verify_cb_call(proc, ok, ctx);
+}
+
static VALUE
ossl_x509store_alloc(VALUE klass)
{
@@ -153,7 +167,7 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
/* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
store->ex_data.sk = NULL;
#endif
- X509_STORE_set_verify_cb(store, ossl_verify_cb);
+ X509_STORE_set_verify_cb(store, x509store_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
/* last verification status */
@@ -661,6 +675,7 @@ Init_ossl_x509store(void)
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_undef_method(cX509Store, "initialize_copy");
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);
@@ -677,6 +692,7 @@ Init_ossl_x509store(void)
x509stctx = cX509StoreContext;
rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
+ rb_undef_method(x509stctx, "initialize_copy");
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);